题解 AT28 【停止問題】

Xial 发布于 2019-09-16 0 次阅读


题面翻译

【题目描述】

Defunge 程序由一个 $R$ 行 $C$ 列的字符数组组成。下面是一个 Defunge 程序的例子:

6>--v.
.^--_@

Defunge 程序从程序的左上角(即第一行第一列)开始执行。它的执行方向一开始为"右",每次朝着执行方向走一步,如果走出界了,要跳到另一边。每走到一个格子上,就要执行这个格子上的命令。 Defunge 程序还有一个存储器,这个存储器只能存储 $[0,15]$ 的一个整数,存储器一开始存储 $\bold{0}$。

在 Defunge 程序中,有且只有 $11+10=21$ 种命令,下面是它们各自的含义:

  • <:把执行方向设置为"左"。
  • >:把执行方向设置为"右"。
  • ^:把执行方向设置为"上"。
  • v:把执行方向设置为"下"。
  • _:如果存储器存储的数字是 $0$,就把执行方向设置为"右",否则设置为"左"。
  • |:如果存储器存储的数字是 $0$,就把执行方向设置为"下",否则设置为"上"。
  • ?:把执行方向设置为"上下左右"中的任意一个(类似于 dfs 把四个方向全搜一遍)。
  • .:什么也不做。
  • @:停止程序。
  • 0-9:把存储器设置为这个字符表示的数值。
  • +:让存储器的数值加 $1$。注意当存储器的数值为 $15$ 时要把它设为 $0$。
  • -:让存储器的数值减 $1$。注意当存储器的数值为 $0$ 时要把它设为 $15$。

现在,给你一个 Defunge 程序,请判断这个程序是否能停止(即执行到命令@)。如果能,输出YES,否则输出NO

【输入格式】

第一行两个正整数 $R,C$,表示这个 Defunge 程序有 $R$ 行 $C$ 列。

接下来 $R$ 行,每行有 $C$ 个字符,描述这个 Defunge 程序。

【输出格式】

一行字符串YESNO,表示这个程序是否能停止。

【样例】

样例输入 $1$:

2 6
6>--v.
.^--_@

样例输出 $1$:

YES

样例输入 $2$:

2 6
5>--v.
.^--_@

样例输出 $2$:

NO

样例输入 $3$:

2 6
.>--v.
.^--?@

样例输出 $3$:

YES

【数据范围】

$1\leq R,C\leq 20$,保证程序里只有上文提到的 $21$ 种命令。

题目描述

problemUrl: https://utpc2011.contest.atcoder.jp/tasks/utpc2011_4

这题其实更像模拟一点

接下来上代码

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
int n, m;
char em[50][50];                     //存储读入
bool vis[50][50][50][50];            //存储当前位置当前状态是否达到过
const int dx[5] = {0, 1, -1, 0, 0};  //移动方向
const int dy[5] = {0, 0, 0, 1, -1};
inline bool dfs(int y, int x, int zhi, int d);  //搜索函数
int main() {
    scanf("
    for (int i = 0; i < n; i++) {  //读入
        scanf("
    }
    puts(dfs(0, 0, 0, 1) ? "YES" : "NO");  //输出【要换行要换行】
    return 0;
}
inline bool dfs(int y, int x, int zhi, int d) {  //四个变量分别为横坐标、纵坐标、当前存储器的值、当前朝向
    y = (y + n)
    x = (x + m)
    if (vis[y][x][zhi][d])
        return 0;           //如果当前位置当前状态已经到达过,就代表这是一个死循环,退出函数
    vis[y][x][zhi][d] = 1;  //标记当前状态
    switch (em[y][x]) {     //分析当前命令
        case '>': {         //向右移动一格
            d = 1;
            break;
        }
        case '<': {  //左移
            d = 2;
            break;
        }
        case 'v': {  //下移
            d = 3;
            break;
        }
        case '^': {  //上移
            d = 4;
            break;
        }
        case '_': {  //判断并移动
            if (!zhi) {
                d = 1;
            } else {
                d = 2;
            }
            break;
        }
        case '|': {  //判断并移动
            if (!zhi) {
                d = 3;
            } else {
                d = 4;
            }
            break;
        }
        case '?': {  //向四个方向分别搜索,有一个方向能到达'@'即可
            for (int i = 1; i <= 4; i++) {
                if (dfs(y + dy[i], x + dx[i], zhi, i))
                    return 1;
            }
            break;
        }
        case '.': {  //什么也不做
            break;
        }
        case '@': {  //到达终点,返回正确
            return 1;
        }
        case '+': {  //存储器的值+1并mod16
            zhi++;
            zhi
            break;
        }
        case '-': {  //存储器的值-1,但为了保持其恒正,我们采取先+15再mod16的策略
            zhi += 15;
            zhi
            break;
        }
        default: {  //否则该处即为数字
            zhi = em[y][x] - '0';
            break;
        }
    }
    if (dfs(y + dy[d], x + dx[d], zhi, d))
        return 1;  //进行下一轮搜索
    return 0;
}

还有一点补充【摘自原题目】

Defunge 与 Befunge 相似。Befunge 的理解可能有助于 Defunge ,但请注意,存在许多差异。

http://ja.wikipedia.org/wiki/Befunge

最后更新于 2022-09-16