圣女

马格里多希望为自己死去却身体不腐的女儿申请圣女。
只是,他不知道神圣的基督教和教皇已经腐朽到了何种地步! 22 年来,他辗转教皇国的各个教堂,但各个教堂都只会以各种理由搪塞、推辞。

教皇国可以看做一个 n∗n 的矩形,每个位置都有一个教堂,教堂有不同的种类。教皇所在的位置是 (n,n),马格里多可以在 (1,1) (1.n) (n,1) 中任意一个位置开始自己的旅程。 A 教堂:马格里多可以在牧师的指引下向上/下/左/右任意一个方向移动一格。 B 教堂:马格里多可以在牧师的指引下向上/下/左/右任意一个方向移动两格。 C 教堂:马格里多可以在牧师的指引下向左上/左下/右上/右下任意一个方向移动一格。 D 教堂:贪婪的牧师或者教皇会卷走马格里多的所有财产,使他不能继续自己的旅程。 马格里多经历每个教堂都需要一天的时间。如果他不能为自己的女儿申请为圣女,请告诉他“Go to find Marx”,否则请告诉他,他的旅程最少需要多少天?

这道题需要用广搜(BFS),类似于走迷宫,简要步骤如下:
(1)找好一个顶点{[1,1];[1,n];[n,1]}

  (2)判断这个顶点属于哪类范畴{'A''B''C''D'},选择不同走法和后果;并将这种走法作为一个结点传入一个队列;

(3)不停地在这个队列中重复第(2)步,也就是广搜;

(4)还需要一个bool型数组判断重复情况

代码如下:

#include <cstdio>
#include <algorithm>
#define FOR(i, l, r) for(int i = l; i <= r; ++i)

using namespace std;

const int N = 1010;
const int M = N * N;
const int dx[4][4] = {0, 0, 0, 0, 1, -1, 0, 0, 2, -2, 0, 0, 1, 1, -1, -1},
dy[4][4] = {0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 2, -2, 1, -1, 1, -1};

int n, l, r, ans, x, y, z, tx, ty, tz, now, q, o;
int a[N][N], f[N][N], b[M], c[M], d[M];
char st[N];

void Bfs()
{
while (l <= r)
{
x = b[l], y = c[l], z = d[l], o = a[x][y];
FOR(i, 0, 3)
{
tx = x + dx[o][i], ty = y + dy[o][i], tz = z + 1;
if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && a[tx][ty] > 0 && !f[tx][ty])
++r, b[r] = tx, c[r] = ty, d[r] = tz, f[tx][ty] = 1;
if (tx == n && ty == n) {ans = tz; return;}
}
++l;
}
}

int main()
{
freopen("saint.in", "r", stdin);
freopen("saint.out", "w", stdout);

scanf("%d", &n);
FOR(i, 1, n)
{
scanf("%s", st);
FOR(j, 0, n - 1)
if (st[j] == 'D') a[i][j + 1] = -1;
else a[i][j + 1] = st[j] - 'A' + 1;
}

if (a[n][n] == -1) {puts("Go to find Marx"); return 0;}
if (a[1][1] > 0) ++r, b[r] = 1, c[r] = 1, d[r] = 1, f[1][1] = 1;
if (a[1][n] > 0) ++r, b[r] = 1, c[r] = n, d[r] = 1, f[1][n] = 1;
if (a[n][1] > 0) ++r, b[r] = n, c[r] = 1, d[r] = 1, f[n][1] = 1;

l = 1, ans = 0; Bfs();
if (ans) printf("%d\n", ans); else puts("Go to find Marx");

return 0;
}

至于其中的FOR用法,权当是一种装逼好了,可以不予理会。

posted @ 2019-07-11 21:03  收废品的老头子  阅读(200)  评论(0编辑  收藏  举报