剪枝很重要,可走的格数小于时间则减去,然后就是奇偶性剪枝
可以把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 但是要求时间是偶数的 都可以直接判断不可达!
#include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <algorithm> #include <math.h> #include <fstream> #include <vector> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdlib.h> using namespace std ; const int maxn = 55; char grid[maxn][maxn]; int vis[maxn][maxn]; int n,m,s,flag; int sx,sy,dx,dy; int dir[4][2] = {1,0,0,1,-1,0,0,-1}; int cango(int x,int y){ return x>=1&&x<=n&&y>=1&&y<=m; } void dfs(int x,int y,int step){ if(flag)return ;//也是一种剪枝吧,不加上这句险些TLE if(step == s){ if(x == dx && y == dy) flag = 1; return; } int temp = s - step - abs(dy - y)-abs(dx - x); if(temp<0||temp&1)//奇偶剪枝 return; for(int i = 0;i < 4;i++){ int xx = x + dir[i][0]; int yy = y + dir[i][1]; if(cango(xx,yy)&&!vis[xx][yy]&&grid[xx][yy] != 'X'){ vis[xx][yy] = 1; dfs(xx,yy,step+1); vis[xx][yy] = 0; } } } int main(){ while(scanf("%d%d%d",&n,&m,&s)&&(n+m+s)){ int wall = 0; for(int i = 1;i <= n;i++) scanf("%s",grid[i]+1); for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++){ if(grid[i][j] == 'S'){ sx = i; sy = j; } if(grid[i][j] == 'D'){ dx = i; dy = j; } if(grid[i][j] == 'X') wall++; } if(n*m - wall <= s){//可能性剪枝 printf("NO\n"); continue; } flag = 0; memset(vis,0,sizeof(vis)); vis[sx][sy] = 1; dfs(sx,sy,0); if(flag) printf("YES\n"); else printf("NO\n"); //for(int i = 1;i <= n;i++) // printf("%s\n",grid[i]+1); } return 0 ; }