链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1110
题意:从起点走到目的地,不能回退到走过的格子,S表示起点,D表示终点,X表示墙,’ . ’表示空格,求在规定时间t内,能否到达终点。n,m表示迷宫的长和宽。
思路:dfs,从起点开始搜,每个格子有四个方向,一个一个地搜。每搜一个格子,就要把格子设为X,因为不能走重复的格子,遇到墙壁或者边界就走不动,走不动就回退,要把格子恢复为‘ . ’,回到上一步的情况。如果某个位置满足条件,就停止搜索。如果全部分支都搜索完了还找不到解,就无解。
其中有两处剪枝,一处是在主函数中,如果空格子数小于等于时间t,那么肯定无解。另一处是在dfs函数中,temp为当前剩余时间与到终点所要花的最短时间的差,如果为负或者是奇数就肯定不能成功。因为如果是奇数的话,就不满足那个,嗯,只能意会不能言传。。。
#include<cstdio> #include<cmath> int n,m,t; int di,dj; int escape; char map[8][8]; int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; void dfs(int si,int sj,int cnt) { if(si>=n||sj>=m||si<0||sj<0) return; if(si==di && sj==dj &&cnt==t) { escape=1; return; } int temp=(t-cnt)-fabs(si-di)-fabs(sj-dj); if(temp<0 || temp%2!=0) return;//剪枝 for(int 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'; dfs(si+dir[i][0],sj+dir[i][1],cnt+1); if(escape) return; else map[si+dir[i][0]][sj+dir[i][1]]='.'; } return; } int main() { int si,sj; int wall; while(scanf("%d%d%d",&n,&m,&t) &&n&&m&&t) { getchar(); wall=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { scanf("%c",&map[i][j]); if(map[i][j]=='S') { si=i; sj=j; } else if(map[i][j]=='D') { di=i; dj=j; } else if(map[i][j]=='X') wall++; } getchar(); } if(n*m-wall<=t)//剪枝 printf("NO\n"); else { escape=0; map[si][sj]='X'; dfs(si,sj,0); if(escape) printf("YES\n"); else printf("NO\n"); } } return 0; }
究竟是我抛弃了历史,还是历史遗弃了我。