lanqiao2020省赛D题REPEAT 程序|文件读取|字符

2021-03-01  本文已影响0人  讲故事的万物

问题描述

本题总分:10 分
附件 prog.txt 中是一个用某种语言写的程序。
其中 REPEAT k 表示一个次数为 k 的循环。循环控制的范围由缩进表达,从次行开始连续的缩进比该行多的(前面的空白更长的)为循环包含的内容。
例如如下片段:
REPEAT 2:
 A = A + 4
 REPEAT 5:
  REPEAT 6:
   A = A + 5
  A = A + 7
 A = A + 8
A = A + 9
该片段中从 A = A + 4 所在的行到 A = A + 8 所在的行都在第一行的循环两次中。
REPEAT 6: 所在的行到 A = A + 7 所在的行都在 REPEAT 5: 循环中。
A = A + 5 实际总共的循环次数是 2 × 5 × 6 = 60 次。
请问该程序执行完毕之后,A 的值是多少?

解析

通过堆栈的方式,用两个数组,一个维护当前行前空格数量用来判断进入新的循环,一个维护当前层次的添加的循环数量。逐行判断,通过冒号判定repeat语句或计算语句,repeat则增加层次并且记录当前倍数,计算语句则直接通过当前倍数和当前行数据对答案计算;通过当前行空格数量与前一行空格数量判断是否减少层次,减少层次通过当前倍数和当前层次添加的循环数量计算减少层次后的倍数,并且对层次减一。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int MAXN=2020;
char s[MAXN];//读取文件
int a[MAXN],b[MAXN];//分别维护当前各层次前空格数量和当前层次增加循环数。
int w;//维护当前行倍数。

int main() {
    freopen("prog.txt", "r", stdin);
    int pos = 0, ans = 0, w = 1;
    gets(s); // 读走第一行的 A = 0
    a[pos] = -1, b[pos] = 1; // 防止在栈空的时候弹栈
    while (gets(s)) {
        int n = strlen(s), p = 0;
        while (s[p] == ' ') 
            p++; // 统计缩进
        while (a[pos] >= p) 
            w /= b[pos--];// 弹掉栈里缩进大于等于当前行的
        if (s[n - 1] == ':') { // 当前行是循环,压栈
            int k = s[n - 2] - '0';
            pos = pos + 1;
            w *= k;
            a[pos] = p, b[pos] = k;
        } else {
            int k = s[n - 1] - '0';
            ans += k * w;
        }
    }
    printf("%d\n", ans);
    return 0;
}

上一篇 下一篇

猜你喜欢

热点阅读