hdu Tempter of the Bone
很典型的dfs题,但是涉及到很多的剪枝 。
奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
奇偶路径的大概意思就是:从初始位置能到达目标位置的任一路径长度 - 初始位置到目标位置的最短长度=偶数
#include"iostream" #include"stdio.h" #include"algorithm" #include"queue" #include"string.h" #include"string" #define mx 105 using namespace std; char maze[mx][mx]; int n,m,T,sx,sy,ex,ey; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; bool flag; bool judge(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m&&maze[x][y]=='.') return true; return false; } void dfs(int x,int y,int t) { if(t>T||flag) return; if(t==T&&x==ex&&y==ey) {flag=true;return;} int temp=abs(x-ex)+abs(y-ey);//当前位置到目标位置的最短路径 temp=T-t-temp; if(temp%2) return;//奇偶剪枝,不加这个一直tle也是醉了 。 for(int i=0;i<4;i++) { int dx=x+dir[i][0]; int dy=y+dir[i][1]; if(judge(dx,dy)) { maze[dx][dy]='X'; dfs(dx,dy,t+1); maze[dx][dy]='.'; } } } int main() { int i,j,blocks; while(cin>>n>>m>>T,n&&m&&T) { flag=false;blocks=0; for(i=0;i<n;i++) { for(j=0;j<m;j++) { cin>>maze[i][j]; if(maze[i][j]=='S') { sx=i;sy=j;maze[i][j]='X'; } else if(maze[i][j]=='D') { ex=i;ey=j;maze[i][j]='.'; } else if(maze[i][j]=='X') blocks++; } } if(n*m-blocks-1>=T)//如果给定的时间数比能走的格子数还要大的话,就肯定不满足条件了 dfs(sx,sy,0); if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }