1.题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1010
2.思路:
题目的意思是S为起点,目标点是D点(门),而X是不能经过的点,问能否刚好在开门的那一秒出去,不能就输出NO能就输出YES。用深搜(DFS)进行搜索,注意剪枝的问题。
奇偶剪枝请自行参考这里“奇偶剪枝”;
3.参考代码一:
#include <iostream>
#include <cmath>
using namespace std;
int n,m,t;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; ///四个方向
int flag; ///标记
int sx,sy,ex,ey; ///(sx,sy)为起点坐标,(ex,ey)为终点坐标
char map[10][10];
void dfs(int x,int y,int step){
int temp=(t-step)-(abs(x-ex)+abs(y-ey)); ///这里的temp的意义请自行参考奇偶剪枝
if(temp<0 || temp%2)
return ;
int i,qx,qy;
for(i=0;i<4;i++)
{
qx=x+dir[i][0];
qy=y+dir[i][1]; ///(qx,qy)为孩子坐标
if(qx>=0 && qx<n && qy>=0 && qy<m && map[qx][qy]=='.') ///判断在边界内并且为'.'
{
map[qx][qy]='X'; ///标记为X表示为经过
dfs(qx,qy,step+1); ///继续搜索下一个点
map[qx][qy]='.'; ///回溯
if(flag)
return ;
}
}
if(map[qx][qy]=='D' || step==t-1) ///如果是目标节点或者时间刚好
flag=1; ///就将flag标记为1
}
int main()
{
int i,j;
while(cin>>n>>m>>t)
{
if(!(n || m || t)) ///如果都为0,则结束
break;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cin>>map[i][j]; ///接收数据
if(map[i][j]=='S')
{
sx=i;
sy=j;
}
if(map[i][j]=='D')
{
ex=i;
ey=j;
}
}
}
flag=0; ///标记默认值为0,表示没有访问过的
dfs(sx,sy,0); ///从起点开始遍历搜索
if(flag)
cout<<"YES\n";
else
cout<<"NO\n";
}
return 0;
}
参考代码二:
#include <stdio.h>
#include <math.h>
#include <string.h>
int n,m,t; ///迷宫的大小及迷宫的门会在第t秒开启
int map[10][10]; ///迷宫地图
int di,dj; ///(di,dj)表示门的位置
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; ///分别表示上下左右四个方向
int escape; ///是否成功逃离的标志,escape==1表示成功逃离
void dfs(int si,int sj,int cnt){ ///(si,sj)为起点,cnt表示花费的时间
int i,temp;
if(si<=0 || si>n || sj<=0 || sj>m) ///边界
return ;
if(si==di && sj==dj && cnt==t) ///成功逃脱
{
escape=1;
return ;
}
///abs(x-ex)+abs(y-ey)表示当前所在的位置和目标的距离(不能走对角线)
///t-cnt是实际还需要的步数
///将它们做差,如果temp<0或者为奇数就不可能到达!
temp=(t-cnt)-abs(si-di)-abs(sj-dj); ///搜索过程中的剪枝
if(temp<0 || temp%2)
return ;
for(i=0;i<4;i++)
{
if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
{
///前进方向,将当前方格设置为墙壁'X'
map[si+dir[i][0]][sj+dir[i][1]]='X';
dfs(si+dir[i][0],sj+dir[i][1],cnt+1); ///搜索下一个位置
if(escape)
return ;
map[si+dir[i][0]][sj+dir[i][1]]='.'; ///后退方向,恢复现场
///要后退恢复的原因是:如果当前搜索方向行不通,该搜索过程要结束了,
///并不代表其他搜索方向也行不通,所以在回退时必须还原到原来的状态,
///保证其他搜索过程不受影响
}
}
return ;
}
int main()
{
int i,j; ///循环变量
int si,sj; ///小狗的起始位置
while(scanf("%d %d %d",&n,&m,&t) && (n || m ||t)) ///%*c作用是忽略换行
{
int wall=0;
getchar();
for(i=1;i<=n;i++)
{
// scanf("%s",&map[i]); ///这种接收方式不同考虑换行的问题
for(j=1;j<=m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='S')
{
si=i;
sj=j;
}
else if(map[i][j]=='D')
{
di=i;
dj=j;
}
else if(map[i][j]=='X')
wall++;
}
getchar();
}
if(n*m-wall<=t)
{
printf("NO\n");
continue;
}
escape=0;
map[si][sj]='X';
dfs(si,sj,0);
if(escape) ///成功逃脱
printf("YES\n");
else
printf("NO\n");
}
return 0;
}