Tempter of the Bone 问题模型 迷宫问题。由起始位置出发t秒时能否到达出口。每秒可以从当前位置沿上、下、左、右四个方向移动一步。 解题报告 dfs+剪枝 /*基础搜索题,dfs dfs的思想是比较直观的,如果不加以剪枝这题的所有状态为4^(n*m),很小的规模(本题中0<n,m<7)就足以TLE 下面介绍本题中我用到的剪枝策略: 1、深度剪枝,如果当前搜索的深度(即时间)已经超过t,则中止搜索; 2、如果迷宫中所以的非'X'数目小与t,则直接输出结果为"NO"; 3、如果已经搜索到结果,中止所有的搜索; 4、奇偶性剪枝,详细介绍如下: 把map看成这样: 0 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1 从 0 的格子走一步,必然为 1 的格子 从 1 的格子走一步,必然为 0 的格子 规律: 0->1或1->0 必然是奇数步 0->0或1->1 必然是偶数步 结论: 当遇到从 0 走向 0 但是要求时间是奇数的, 或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达! 5、如果从当前的位置到目标位置所需的理论上的最少时间大于了当前剩余的时间,直接判断为不可到达 */ /* 变量说明: sx,sy为初始位置,tx,ty为目标位置,out为1表示走出迷宫 */ #include<iostream> using namespace std; char maze[7][7]; int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0},sx,sy,tx,ty,r,c,t; bool out; bool judge(int x,int y){ return (x>=0 && x<r && y>=0 && y<c && maze[x][y]!='X'); } void dfs(int deep,int curx,int cury){ if(deep==t && curx==tx && cury==ty) out=1; if(deep>t||out) return ; //剪枝 1、3 if(t-deep<abs(curx-tx)+abs(cury-ty)) return; //剪枝 5 if((t-deep)%2!=(abs(curx-tx)+abs(cury-ty))%2) return ; //剪枝 4 for(int i=0;i<4;i++){ int x,y; x=curx+dx[i]; y=cury+dy[i]; if(judge(x,y)){ maze[x][y]='X'; dfs(deep+1,x,y); maze[x][y]='.';//这里是回溯的精华 } } } int main(){ while(cin>>r>>c>>t,r||c||t){ int cnt=0; for(int i=0;i<r;i++) for(int j=0;j<c;j++){ cin>>maze[i][j]; if(maze[i][j]!='X') cnt++; if(maze[i][j]=='S'){sx=i;sy=j;} if(maze[i][j]=='D'){tx=i;ty=j;} } maze[sx][sy]='X'; if(cnt<t) cout<<"NO"<<endl;//剪枝2 else{ out=0; dfs(0,sx,sy); if(out) cout<<"YES"<<endl; else cout<<"NO"<<endl; } } return 0; }