http://acm.hdu.edu.cn/showproblem.php?pid=1010
题意:在n*m的地图上,标记为S的为狗狗的起点,D为门,问能否恰好以给定t的时间到达D,能就输出YES,否则NO,每个点只能走一次。
思路:dfs问题,找到一条长度恰好为t的路径,不一定是最短路路径,所以不能单纯用bfs。
但是 一般dfs会超时,所以要剪枝,这里主要用到奇偶性剪枝,参考链接:
http://baike.baidu.com/view/7789287.htm?fr=alad
http://www.slyar.com/blog/depth-first-search-even-odd-pruning.html
下面是优化后的代码:46ms
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
char map[9][9];
int n,m,t,di,dj;
bool escape;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int si,int sj,int cnt)
{
if(cnt>10000) return;
if(escape) return;
if(si>n||sj>m||si<=0||sj<=0) return;
if(cnt==t&&si==di&&sj==dj) escape=1; //找到恰好为t的路径
if(escape) return;
if(cnt>=t) return; //如果当前步数比t大
int i,temp;
temp=(t-cnt)-abs(si-di)-abs(sj-dj); //奇偶性剪枝,t-cnt是表示剩余的步数,后面两个绝对值之和是表示当前点到终点的最短路径
if(temp<0||temp&1) return; //结果不能小于0或者为基数,因为上面的差一定为偶数才有解。
for(i=0;i<4;i++){
if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
{
map[si+dir[i][0]][sj+dir[i][1]]='X';
dfs(si+dir[i][0],sj+dir[i][1],cnt+1);
map[si+dir[i][0]][sj+dir[i][1]]='.';
}
}
return;
}
int main()
{
int i,j,si,sj;
while(cin>>n>>m>>t)
{
if(n==0&&m==0&&t==0) break;
int wall=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>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++;
}
if(n*m-wall<=t) //如果地图全部能够走的步数加起来都小于等于t,表示一定不能达到。
{
cout<<"NO"<<endl;
continue;
}
escape=0;
map[si][sj]='X';
dfs(si,sj,0);
if(escape) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
原文地址:http://blog.csdn.net/u012773338/article/details/39236901