原题:http://acm.hdu.edu.cn/showproblem.php?pid=1010
题意:从S走到D,其中X是墙,不能走;给定时间 t ,问能否从S到D正好花费 t 时间(一步即为一秒);
思路:用DFS+剪枝;
此处有两种剪枝:
1、从S到D的最短时间是 tmp = abs(sx-dx)+abs(sy-dy),如果 tmp > t,显然是“NO”;
2、如果 tmp <= t,那么我们要走到D就要往回走几步,如果你往左多走了一步,那么势必就要往右也走一步,才能又回到D;所以剩余步数 cnt = t - tmp 就一定是偶数;
上述的第2种剪枝方法叫做“奇偶性剪枝”;
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10;
int n, m, t;
string Map[maxn];
int sx, sy, dx, dy;
bool flag;
bool vis[maxn][maxn];
void DFS(int x, int y, int step){
if(x < 0 || x >= n || y < 0 || y >= m) return;
if(x == dx && y == dy){
if(step == t) flag = true;
return;
}
if(x-1 >= 0 && Map[x-1][y] != 'X' && !vis[x-1][y]){
vis[x-1][y] = true;
DFS(x-1, y, step+1);
vis[x-1][y] = false;
}
if(flag) return;
if(Map[x+1][y] != 'X' && x+1 < n && !vis[x+1][y]){
vis[x+1][y] = true;
DFS(x+1, y, step+1);
vis[x+1][y] = false;
}
if(flag) return;
if(y-1 >= 0 && Map[x][y-1] != 'X' && !vis[x][y-1]){
vis[x][y-1] = true;
DFS(x, y-1, step+1);
vis[x][y-1] = false;
}
if(flag) return;
if(Map[x][y+1] != 'X' && y+1 < m && !vis[x][y+1]){
vis[x][y+1] = true;
DFS(x, y+1, step+1);
vis[x][y+1] = false;
}
return;
}
int main(){
while(cin>>n>>m>>t){
memset(vis, false, sizeof vis);
if(n == 0 && m == 0 && t == 0) break;
for(int i = 0;i<n;i++){
cin>>Map[i];
for(int j = 0;j<m;j++){
if(Map[i][j] == 'S') sx = i, sy = j;
if(Map[i][j] == 'D') dx = i, dy = j;
}
}
int tmp = abs(sx-dx)+abs(sy-dy);
if(tmp > t || (t-tmp) % 2 != 0){
cout<<"NO"<<endl;
continue;
}
flag = false;
vis[sx][sy] = true;
DFS(sx, sy, 0);
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}