首页 > 代码库 > hdu-1010 Tempter of the Bone

hdu-1010 Tempter of the Bone

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;
}




 

hdu-1010 Tempter of the Bone