题意:给定起始点与终止点,中间有些地方有墙,其他地方都可以走,走一格花费1,上下左右走,问能否在t时间恰好到达终点。
思路:dfs。这个需要一个奇偶剪枝,第一次学。TLE了几次,看的网上解题报告才知道用到这个剪枝。
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
#include<iostream> #include<cmath> using namespace std; char map[10][10]; int n,m,t; int dir[4][2]={0,1,1,0,0,-1,-1,0}; int vis[10][10]; bool flag; int sx,sy,ex,ey; void dfs(int x,int y,int nt)//当前位置以及时间 { if(flag)return ;//找到就结束,无此步依旧TLE if(x<0||x>=n||y<0||y>=m)return ; if(nt>t)return ; if(map[x][y]=='D'&&nt==t) { flag=true; return ; } int temp=fabs(double(x-ex))+fabs(double(y-ey));//奇偶剪枝:最短的时候就是起始点坐标之差求和sum。 //t-sum为偶数时才有可能在时间t内到达指定位置。否则不可能到达。 temp=t-temp-nt; if(temp&1) return ; for(int i=0;i<4;i++) { int nx=x+dir[i][0]; int ny=y+dir[i][1]; if(!vis[nx][ny]) { vis[nx][ny]=1; dfs(nx,ny,nt+1); vis[nx][ny]=0; } } } int main() { while(cin>>n>>m>>t) { int k=0; if(n==0&&m==0&&t==0)break; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { cin>>map[i][j]; if(map[i][j]=='S') { sx=i; sy=j; vis[i][j]=1; } else if(map[i][j]=='D') { ex=i; ey=j; vis[i][j]=0; } else if(map[i][j]=='X') { vis[i][j]=1; k++; } else vis[i][j]=0; } flag=false; if(n*m-k>t) dfs(sx,sy,0); if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }