4 1101 0001 1100 1001
east north
这个题目真是坑。。每个细节都要注意好,不然就会容易TLE和WA。。首先BFS坑定没法搜的,就只能ID了。h函数要设计好,我一开始偷懒就设置的所有点到与它最近的边缘的直线距离的最大值。。然后T得我说不出话。。修改了一下,就是每个点到与它最近边缘的准确最小距离的最大值,这就需要BFS预处理,从边缘上每个点出发到棋盘内部每个点的距离一开始就算出来。然后还是TLE!!!!我想了半天,发现有个细节,就是边缘上是1的点的话就不需要从他开始BFS。。然后我就实在想不出撒子还可以把h函数弄得更大的办法了。就交了一发。。然后就WA了。。还好我马上反应过来我limit是从1开始的,试了个所有0都在边界的数据,果然给我输出了个east。。然后改了这里就过了。
还有一点,很多ID的题里面一个剪枝就是记录上一步的方向,这一步肯定不能走上一步的反方向。但是这道题不一样,即使走上一步的反方向并不一定会回到上一步完全一样的局面。
还有,网上大多数都是在dfs内部传数组表示状态,我觉得搜索的时候尽量不要传数组那样大的整个状态,因为这样如果是爆内存了它很可能提示的是TLE而不是RE。。很confusing。。宁肯花点时间复原。
程序最下面有一组我自己想比较卡的数据,能秒出那就差不多了。
#include<cstdio> #include<cstring> #include<queue> #include<utility> using namespace std; #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define pii pair<int,int> #define MP make_pair int N, limit, ok; const int dd[4][2] = {{0,1},{-1,0},{1,0},{0,-1}}; const char dname[4][7] = {"east","north","south","west"};//字典序 char a[15][15]; int x[100], y[100], cnt;//棋盘中所有人的下标 int res[100]; int dis[15][15]; int geth() { int res = 0; for (int i = 1; i<=cnt; ++i) res = Max(res, dis[x[i]][y[i]]); return res; } void dfs(int i)//这个i实际表示待确定的步骤。 { int h = geth(); if (!h) { ok = 1; return; } if (i+h-1 > limit || i>limit || ok) return; bool mdf[85], flag = 0; //mdf:是否修改过,需要复原。flag:如果当前移动根本无效,直接跳过 for (int t = 0; t<4 && !ok; ++t) { memset(mdf, 0, sizeof mdf); for (int j = 1; j<=cnt; ++j) { if (x[j]==1||x[j]==N||y[j]==1||y[j]==N) continue; if (a[x[j]+dd[t][0]][y[j]+dd[t][1]]=='1') continue; x[j] += dd[t][0]; y[j] += dd[t][1]; flag = mdf[j] = 1; } res[i] = t; if (flag) { dfs(i+1); for (int j = 1; j<=cnt; ++j) if (mdf[j]) x[j] -= dd[t][0], y[j] -= dd[t][1]; } } } void BFS(int x, int y) { queue<pii > Q; Q.push(MP(x,y)); dis[x][y] = 0; pii s; int tx, ty; while (!Q.empty()) { s = Q.front(); Q.pop(); for (int i = 0; i<4; ++i) { tx = s.first + dd[i][0]; ty = s.second + dd[i][1]; if (tx<1 || ty<1 || tx>N || ty>N) continue; if (a[tx][ty]=='1') continue; if (dis[tx][ty] <= dis[s.first][s.second]+1) continue; dis[tx][ty] = dis[s.first][s.second] + 1; Q.push(MP(tx, ty)); } } } int main() { int i, j, flag = 0; while (~scanf("%d", &N)) { for (i = 1; i<=N; ++i) scanf("%s", a[i]+1); cnt = 0; for (i = 2; i<N; ++i) for (j = 2; j<N; ++j) { if (a[i][j]=='0') { ++cnt; x[cnt] = i; y[cnt] = j; } } for (i = 1; i<=N; ++i) for (j = 1; j<=N; ++j) dis[i][j] = 99999; for (i = 1; i<=N; ++i) { if (a[i][1] == '0') BFS(i, 1); if (a[i][N] == '0') BFS(i, N); if (a[1][i] == '0') BFS(1, i); if (a[N][i] == '0') BFS(N, i); } ok = 0; limit = 0;//一定从零开始 while (1) { dfs(1); if (ok) break; ++limit; } if (flag++) puts(""); for (i = 1; i<=limit; ++i) puts(dname[res[i]]); } return 0; } /* 8 10111111 10001001 11100011 10001111 11100001 10111011 10000001 11111111 answer:seeeenwnnwswnnwnwwn */
4 1101 0001 1100 1001
east north