link:点击打开链接
Tempter of the Bone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 72043 Accepted Submission(s): 19817
The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
NO YES
#include<stdlib.h>
#include<string.h>
int n,m,time,flag,da,db,sa,sb;
char a[10][10];
int d[4][2]={1,0,0,1,-1,0,0,-1};
int visit[10][10];
void dfs(int x,int y,int step)
{
int xx,yy,i;
if(x==da&&y==db)
{
if(step==time)
flag=1;
return;
}
if(flag)return;//剪枝(可以不要)
if(step==time)return;//剪枝(不管是否能够到达,都要返回,flag已经记录下结果了)
for(i=0;i<4;i++)
{
xx=x+d[i][0];
yy=y+d[i][1];
if(xx<0||yy<0||xx>n-1||yy>m-1||visit[xx][yy]==1||a[xx][yy]=='X')
continue;
visit[xx][yy]=1;
//(可能很多人很迷茫这一点,这是两种情况1:如果走a[xx][yy]这一点,就搜索dfs(xx,yy,step+1);如果没有搜索到,跳出后visit[xx][yy]=0;此处标记为为走过)
dfs(xx,yy,step+1);
visit[xx][yy]=0;
if(flag)return;//剪枝||外搜索的返回
}
}
int main()
{
int i,j;
while(scanf("%d%d%d",&n,&m,&time)!=-1,n!=0||m!=0||time!=0)
{
getchar();
for(i=0;i<n;i++)
{
scanf("%s",a[i]);
for(j=0;j<m;j++)
{
if(a[i][j]=='S')
{sa=i,sb=j;}
if(a[i][j]=='D')
{da=i;db=j;}
}
}
if((abs(sa-sb)+abs(da-db)+time)%2||abs(sa-da)+abs(sb-db)>time)//剪枝一;
{printf("NO\n");continue;}
memset(visit,0,sizeof(visit));
flag=0;
visit[sa][sb]=1;
dfs(sa,sb,0);
visit[sa][sb]=0;
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
----------------------------------------------------------------------------------------------
mycode:
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
char map[10][10];
int vis[10][10];
int d[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int n,m,t,ex,ey,fg,sx,sy;
void dfs(int step,int x,int y)
{
int xx,yy,i;
if(step==t&&x==ex&&y==ey)
{
fg=1;
return;
}
if(step==t)
return;
for(i=0;i<4;i++)
{
xx=x+d[i][0];
yy=y+d[i][1];
if(xx<0||yy<0||xx>n-1||yy>m-1||vis[xx][yy]==1||map[xx][yy]=='X')
continue;
vis[xx][yy]=1;
dfs(step+1,xx,yy);
vis[xx][yy]=0;
if(fg)return;//剪枝||外搜索的返回
}
}
int main()
{
int i,j;
while(scanf("%d%d%d",&n,&m,&t)!=EOF&&n)
{
getchar();
for(i=0;i<n;i++)
{
scanf("%s",map[i]);
for(j=0;j<m;j++)
{
if(map[i][j]=='S')
{
sx=i;
sy=j;
}
else if(map[i][j]=='D')
{
ex=i;
ey=j;
}
}
}
if((abs(sx-ex)+abs(sy-ey)+t)%2||abs(sy-ey)+abs(sx-ex)>t)//剪枝一;
{printf("NO\n");continue;}
memset(vis,0,sizeof(vis));
fg=0;
vis[sx][sy]=1;
dfs(0,sx,sy);
if(fg)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
不是很难的搜索题,但要注意,用深搜时一定要剪枝;否则很容易超时,
剪枝分为:
1.奇偶剪枝:矩阵都可以写成奇偶相间的形式;
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
其中,只要是由0->1,或者1->0,都是奇数步;
而由0->0,1->1,的都是偶数步;
所以只要步子数与时间的奇偶性不同,就一定不能到达,要剪掉;
2:路径剪枝:
有一个最短路径,如果最短路径的步数都大于时间,则肯定不能到达,要剪掉,abs(sa-da)+abs(sb-db),是很粗糙的最短路径,因为路径中可能有不能走的墙,可以用动态存储最短路径,这个题还没必要;
如果在路径中,还没有到达,步子数就已经跟时间相等,则此路径不可能,剪掉;
题目中有深搜便捷的判断方法:比如用step存步子数与时间作比较;用flag做深搜的返回值,搜索过程中记录flag的变化,然后只要遇到可以减掉的过程,就直接返回;