#include <cstdlib> #include <cstdio> #include <cstring> #include <iostream> #include <queue> #define INPUT using namespace std; const int c0de4fun = 10; int x[4] = {1,-1,0,0}; int y[4] = {0,0,1,-1}; int maze[c0de4fun][c0de4fun]; /** Problem :HDOJ/HDU1072 - Nightmare Begin Time:Unknown End Time:Unknown Test Data: 有一个146K的超级大测试文件,需要的可以PM我 Output:用本程序对拼即可 思路: 广度优先搜索+模拟,不用剪枝,不用记录已访问节点。记得把bombResetEquipment改成0或者改成1 教训: WA了几次,教训主要有两点: 1,看题要仔细,本题中bombResetEquipment只能用一次就消失了,我以为能用很多次。 2,在搜索中,自带限制条件的,一般来说就不用mark已经访问过的节点了 所谓的限制条件,就是在一定步数之后可以让节点消失(不被重复访问)的条件 本题中我的重大!!!错误!!!就在于,当访问了bombResetEquipment之后就 mark掉这个点,然后把visited清空,并记录每个bombResetEquipment的位置,重新从这几个位置开始搜索。 但是这会导致一个问题,有些未扩展的状态就被清空了。在146K的测试数据中可以看到这点 这种情况可以是以下状况: 遇到了BRE,visited清空了,但是当前从BRE开始搜索,导致 从开始'3'点通往出口的某个点得状态变成了“已访问”,并且从BRE开始搜索不能达到出口 但是从开始点搜索是可以达到的,由于开始点通往出口的点被标注visited了,所以不能从这个点搜索了。 导致不出正确结果。 */ struct node { int x; int y; int time; int depth; }; queue<node> nodes; void Solve(int startx,int starty,int N,int M) { node tmp; bool isExisted = false; tmp.depth = 0; tmp.time = 6; tmp.x = startx; tmp.y = starty; nodes.push(tmp); while( !nodes.empty() ) { tmp = nodes.front();nodes.pop(); if( maze[tmp.x][tmp.y] == 4) { tmp.time = 6; maze[tmp.x][tmp.y] = 0; ///这里还要mark一下 } if( maze[tmp.x][tmp.y] == 3) { printf("%d\n",tmp.depth);isExisted = true;break; } for(int i = 0 ; i < 4; i++) { node tmp1 = tmp; tmp1.x = tmp.x + x[i]; tmp1.y = tmp.y + y[i]; tmp1.depth = tmp.depth + 1; tmp1.time = tmp.time - 1; if( tmp1.x < 1 || tmp1.x > N || tmp1.y < 1 || tmp1.y > M) continue; //数组越界 if( tmp1.time <= 0 ) continue; if ( maze[tmp1.x][tmp1.y] == 0 ) continue; nodes.push(tmp1); } } if(!isExisted) { printf("-1\n"); } while(!nodes.empty()) nodes.pop(); } int main() { int T; int N,M; int startx,starty; #ifdef INPUT freopen("b:\\acm\\hdu1072\\input.txt","r",stdin); //freopen("b:\\acm\\hdu1072\\output.txt","w",stdout); #endif scanf("%d",&T); for(int t = 0 ; t < T; t++) { memset(maze,0,sizeof(int)*c0de4fun*c0de4fun); scanf("%d%d",&N,&M); for(int i = 1; i<=N; i++) { for(int j = 1; j<=M; j++) { scanf("%d",&maze[i][j]); if(maze[i][j] == 2) { startx = i; starty = j; } } } Solve(startx,starty,N,M); } #ifdef INPUT fclose(stdin); //fclose(stdout); #endif return 0; }