比赛遇到了这种不是求最小的步骤而是某一时刻到达某一地点的题目,但却一直用BFS杠,QAQ,后来才知道应该用DFS+剪枝
题目链接:Tempter of the Bone
思路分析:
这道题是求T时刻能不能正好到达,我们用DFS递归下去,如果在小于T时刻就到了目的地,他会继续递归下去,直到无路可走,就会退回来试试走别的路,直到试探到正好T时刻到。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
int vis[8][8],bx,by,ex,ey,n,m,T,flag;
char a[9][9];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int x,int y,int time)
{
int i,xx,yy;
vis[bx][by]=1;
if(flag==1)
return;
if(time>T)
return;
if(abs(x-ex)+abs(y-ey)>(T-time) || abs(T-abs(x-ex)-abs(y-ey)-time)%2==1) //奇偶剪枝
return;
if(a[x][y]=='D' && time==T)
{
flag=1;
return;
}
for(i=0;i<4;i++)
{
xx=x+dir[i][0];
yy=y+dir[i][1];
if(xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && a[xx][yy]!='X')
{
vis[xx][yy]=1;
dfs(xx,yy,time+1);
vis[xx][yy]=0; //记得取消标记,试探别的路
}
}
return;
}
int main()
{
int i,j;
while(scanf("%d %d %d",&n,&m,&T)!=EOF && n)
{
flag=0;
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
cin>>a[i][j];
if(a[i][j]=='S')
{
bx=i;
by=j;
}
if(a[i][j]=='D')
{
ex=i;
ey=j;
}
}
dfs(bx,by,0);
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
一些小的剪枝都要写上,要不很容易TLE,好久没写dfs了,在小细节上各种WA,看来还是练少了。