题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
这题一开始没有理解题目的意思,以为随便写个bfs求最短路径就可以了。后面认真读题才发现题意是一定是要在题目规定的步数到终点才可以。
思路:强行暴力的dfs肯定会超时所以要剪枝才可以。
奇偶剪枝:根据曼顿距离公式,令起点为nx,ny,终点为dx,dy那么最短的距离是dl=abs(dx-nx)+abs(dy-ny);那么所有的路径的奇偶性都和最短距离的奇偶性相同。根据这点可以进行剪枝。
剪枝2:这一点剪枝依旧无法明白为什么 但是就是符合设墙体数是wall,限定时间是t,总块数为n*m,当t>=n*m-wall,则一定是输出no;
贴代码:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
string p[10];
int sx,sy,ex,ey,n,m,t;
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
bool flag;
int zero(int a)
{
return a>0?a:-a;
}
void dfs(int x,int y,int time)
{
//cout<<x<<' '<<y<<' '<<time<<endl;
if (time==t&&x==ex&&y==ey)
{
flag=1;
return ;
}
if (flag)
return ;
int temp=(t-time)-(zero(x-ex)+zero(y-ey));
if (temp<0||temp%2)
return ;
// cout<<"::"<<endl;
for (int i=0;i<4;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if (xx<0||xx>=n||yy<0||yy>=m)
continue;
//cout<<p[xx][yy]<<i<<endl;
if (p[xx][yy]!='X')
{
p[xx][yy]='X';
dfs(xx,yy,time+1);
p[xx][yy]='.';
}
if (flag)
return ;
}
}
int main()
{
while (cin>>n>>m>>t)
{
if (n==0&&m==0&&t==0)
break;
int wall=0;
for (int i=0;i<n;i++)
cin>>p[i];
//for (int i=0;i<n;i++)
//cout<<p[i]<<endl;
for (int i=0;i<n;i++)
{
for (int j=0;j<m;j++)
{
if (p[i][j]=='X')
wall++;
else if (p[i][j]=='S')
{
sx=i;
sy=j;
}
else if (p[i][j]=='D')
{
ex=i;
ey=j;
}
}
}
//cout<<ex<<ey<<sx<<sy<<t;
if (n*m-wall<=t)
{
cout<<"NO"<<endl;
continue;
}
flag=0;
p[sx][sy]='X';
dfs(sx,sy,0);
if (flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}