题目链接:HDU 1010
n*m的迷宫,'X’代表墙,'S’起点,‘D’出口,’.'代表路,问能不能在 t 秒走出。
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
NO
YES
注意题目要求是正好在 t 秒是否能走出,不能用BFS,因为bfs找到的最短路不一定是需要的 t 秒,且bfs是在邻点逐步扩张,可能会把需要的点占去。用DFS+回溯,但是需要考虑剪枝,即一旦判断某一步时再往下走的话无论如何都不会到达终点或者满足题意,直接跳出判断,输出结果。
奇偶剪枝
1,奇偶剪枝
设起点(x1,y1),终点(x2,y2),那么从起点到终点的最短路劲为abs(x1-x2)+abs(y1-y2)。
从起点到终点走的任意非最短路径所走的步数减去最短路径的步数一定为偶数
若为奇数,则一定不能到达。
2,路径剪枝
当走的路用去的时间等于 t 时且还没有走到终点,结束。
当全图能走的路花费时间小于 t 时,结束。
代码:
#include <iostream>
#include <cmath>
#include <cstring>
const int maxn = 10;
using namespace std;
char map[maxn][maxn];
int dis[][2]= {1,0,-1,0,0,1,0,-1};
int n,m,t,beg,endd,flag;
void dfs(int xx,int yy,int ans)
{
if(xx==beg&&yy==endd&&ans==t)
{
flag=1;
return ;
}
int p=t-ans-(abs(xx-beg)+abs(yy-endd));//当前剩余步数(t-ans)减去最短路径所需步数(abs(xx-beg)+abs(yy-endd))
if(p<0||p&1)//判断奇偶或是否能走出
return;
for(int i=0; i<4; i++)
{
int dx=xx+dis[i][0];
int dy=yy+dis[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&map[dx][dy]!='X')
{
map[dx][dy]='X';//将走过的路变为墙
dfs(dx,dy,ans+1);
map[dx][dy]='.';//回溯,将该点重置为路
}
}
return;
}
int main()
{
int x,y,obs;
while(cin>>n>>m>>t&&n&&m&&t)
{
flag=0,obs=0;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
cin>>map[i][j];
if(map[i][j]=='S')
x=i,y=j;
if(map[i][j]=='D')
beg=i,endd=j;
if(map[i][j]=='X')
obs++;
}
if(n*m-obs<=t)//当全图能走的路花费时间小于 t 时,结束
{
cout<<"NO"<<endl;
continue;
}
map[x][y]='X';
dfs(x,y,0);
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}