4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
NO YES
要点:
1、每个block只能走一次
2、要求恰好某个给定的时间到达出口
算法分析:
迷宫==搜索无疑,关键在于剪枝。
1、若时间大于剩余可行走block,则必定失败。
2、
可以把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 但是要求时间是偶数的 都可以直接判断不可达!关于这句话在本题中的使用,我是这样理解的,假设有一条最短路径p,我们若每偏离p路径一次,就需要增加2或者0才能达到目的地,因此该路径的奇偶性与时间必定等同。
深搜代码如下:
# include <iostream> char map[9][9]; int n,m,t,di,dj; bool escape; int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; void dfs(int si,int sj,int cnt) { int i,temp; if(si>n||sj>m||si<=0||sj<=0) return; if(cnt==t&&si==di&&sj==dj) escape=1; if(escape) return; temp=(t-cnt)-abs(si-di)-abs(sj-dj); //(t-cnt)为剩余分钟,abs(si-di)+abs(sj-dj)为最少需要步数, //若前者小于后者则一定失败,若二者的奇偶性不同也一定失败 if(temp<0||temp&1) return; for(i=0;i<4;i++){ //尝试相邻四个可能位置 if(map[si+dir[i][0]][sj+dir[i][1]]!='X') { map[si+dir[i][0]][sj+dir[i][1]]='X'; //已走过,置为x dfs(si+dir[i][0],sj+dir[i][1],cnt+1); map[si+dir[i][0]][sj+dir[i][1]]='.'; //向上一步回溯时把该方格仍置为空 } } return; } int main() { int i,j,si,sj; while(std::cin>>n>>m>>t) { if(n==0&&m==0&&t==0) break; int wall=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { std::cin>>map[i][j]; if(map[i][j]=='S') { si=i; sj=j; } //si,sj 记下入口位置 else if(map[i][j]=='D') { di=i; dj=j; } //di,dj记下出口位置 else if(map[i][j]=='X') wall++; //统计墙的总数 } if(n*m-wall<=t) //可走的block的总数小于时间 { std::cout<<"NO"<<"\n"; continue; } escape=0; map[si][sj]='X'; dfs(si,sj,0); if(escape) std::cout<<"YES"<<"\n"; else std::cout<<"NO"<<"\n"; } return 0; }
HDU 1010 Tempter of the Bone(DFS+奇偶性剪枝),布布扣,bubuko.com
HDU 1010 Tempter of the Bone(DFS+奇偶性剪枝)
原文地址:http://blog.csdn.net/u014492609/article/details/38510057