hdu1010Tempter of the Bone(dfs+奇偶剪枝)

来源:互联网 发布:药房软件 编辑:程序博客网 时间:2024/06/05 13:25

题目大意:给一张迷宫地图,看看是否有等够在给的时间刚好到达终点,并且走过的不能重复走,记住,是刚好到达!!!

思路:搜索题,一开始只是轻微地作找到方案,作标记flag的剪枝,发现超时,原来还要奇偶剪枝,就是你一步一步走,如果你的位置到终点最小路程与剩余时间做差刚好是个奇数时,就要去掉。可能你会想,我们多走几格不就好了?但是你可以在稿纸上模拟一下,可以知道任何到达终点的路程(切记不能重复)刚好和最短路程的奇偶性一样。这点大牛们已经帮我们证明过了,当然你数学够6的话可以试试,反正身为菜鸟的我是不会啦,言归正传,剩下的就是搜索的基本思路啦,不知道那些排行榜的0ms的怎么写得(膜拜!),我的只能109ms,大佬又发现能再优化的一定告诉我哈!

代码如下:

#include<stdio.h>#include<string.h>#include<math.h>int book[15][15],n,m,flag,rx,ry;char map[15][15];int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};bool pan(int x,int y){if(x<0||x>=n||y<0||y>=m||map[x][y]=='X')return false;return true;}void dfs(int time,int x,int y){if(time<0)return ;if(time==0){if(map[x][y]=='D'){flag=1;return ;}return ;}int a,b,i;a=abs(x-rx);b=abs(y-ry);if(time-a-b<0||(time-a-b)%2)  //如果剩余的实践无法达到终点或者达到终点后还有时间就去掉(奇偶剪枝)return ;for(i=0;i<4;i++){a=x+next[i][0];b=y+next[i][1];if(pan(a,b) && !book[a][b]){book[a][b]=1;dfs(time-1,a,b);book[a][b]=0;}if(flag) return ;  //如果已经找到方案就不用再搜了(剪枝)}return ;}int main(){int i,j,time,x,y,p;while(~scanf("%d%d%d",&n,&m,&time) && (n||m||time)){getchar();memset(book,0,sizeof(book));memset(map,0,sizeof(map));for(i=p=0;i<n;i++)scanf("%s",map[i]);for(i=0;i<n;i++)for(j=0;j<m;j++)if(map[i][j]=='S'){x=i,y=j;}else if(map[i][j]=='D'){rx=i,ry=j;}else if(map[i][j]=='X'){p++;}if(n*m-p-time<=0)   //剪枝,容易遗忘等于的情况{printf("NO\n");continue;}book[x][y]=1;flag=0;dfs(time,x,y);if(flag)printf("YES\n");elseprintf("NO\n");}return 0;}