Sample Input:
4 4 5Sample Output:
NOYES
详细代码及解析如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <algorithm>
#define MAXN 100
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
char Map[MAXN][MAXN]; //地图
int N, M, T; //地图size,逃脱时间
bool escape = false; //能否逃脱
int Sx, Sy, Ex, Ey, wall; //起始坐标,目标坐标,墙壁数目
const int dx[] = {0, 0, 1, -1}; //方向数组
const int dy[] = {-1, 1, 0, 0};
bool check(int x, int y) //判断是否能往下一个格子前进
{
return x>=0 && y>=0 && x<N && y<M && Map[x][y]!='X';
}
void DFS(int px, int py, int cnt)
{
if(px==Ex && py==Ey && cnt==T) { //顺利逃脱
escape = true;
return ;
}
//abs(x-ex)+abs(y-ey)表示现在所在的格子到目标格子的距离(不能走对角线)
//T-cnt是实际还需要的步数,将它们做差
//如果tmp<0或tmp为奇数,那就不可到达!
int tmp = (T-cnt) - fabs(px-Ex) - fabs(py-Ey); //搜索过程中的奇偶剪枝
if(tmp < 0 || tmp % 2) return ;
for(int i=0; i<4; i++) {
int xx = px + dx[i];
int yy = py + dy[i];
if(check(xx, yy)) {
Map[xx][yy] = 'X'; //将当前方格设置为墙壁
DFS(xx, yy, cnt+1); //深度遍历
if(escape) return ;
Map[xx][yy] = '.'; //状态恢复,回溯
}
}
return ;
}
int main(int argc, char *argv[])
{
while(~scanf("%d %d %d", &N, &M, &T) && N || M || T) {
wall = 0;
for(int i=0; i<N; i++) { //地图输入
scanf("%s", Map[i]);
for(int j=0; Map[i][j]; j++) {
if(Map[i][j] == 'S') { Sx=i, Sy=j; }
else if(Map[i][j] == 'D') { Ex=i, Ey=j; }
else if(Map[i][j] == 'X') wall++; //统计墙的块数
}
}
if(N*M-wall <= T) { //搜索前的剪枝
puts("NO");
continue;
}
escape = false; //初始化为false
Map[Sx][Sy] = 'X'; //走过的块变成墙,保证一次走过
DFS(Sx, Sy, 0);
if(escape) puts("YES");
else puts("NO");
}
return 0;
}
HDU 1010 && ZOJ 2110 Tempter of the bone (DFS + 奇偶剪枝)
原文地址:http://blog.csdn.net/keshacookie/article/details/44021213