hdu1010 (dfs+奇偶剪枝)

关于奇偶剪枝:

下面给出一个奇偶矩阵
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0

我们观察到:
如果从标记有0的位置到标记有1的位置,需要走的步数是奇数。
(0,0)->(1,2),你无论选择哪条路所需要的步数都是奇数。
如果从标记有0的位置到标记有0的位置,需要走的步数是偶数数
(0,0)->(2,2),你无论选择哪条路所需要的步数都是偶数。

简单来说终点与起点奇偶性一样那么就需要偶数步,不一样则是奇数步.

我们从一个点到另一个点的距离(不走对角线)等于什么?
/*
S是起点,D是终点,X 是墙,+是空地
*/

1.没有障碍的情况
S+++
++++
++++
+++D
S->D的距离都是abs(si-di)+abs(sj-dj),其中si,sj表示S坐标,di,dj表示D 坐标.证明省略。
2.有障碍的情况
S++x
XX+X
+++X
+XXX
+++D
我们不能使用之前的那种走法。
我们把该路径画下来
++
+
+++
+
++++,
然后平移到边上

+++
+++
+
++++
与最短路径对比
+
+
+
++++
对比结果:这里写图片描述
可以发现所需要的步数=最短距离+一个偶数,无论怎样走都是这个结果。这个也就为我们hdu1010这个题目提供了剪枝想法。

上题目:Tempter of the Bone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 90741 Accepted Submission(s): 24687

Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.

Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

‘X’: a block of wall, which the doggie cannot enter;
‘S’: the start point of the doggie;
‘D’: the Door; or
‘.’: an empty block.

The input is terminated with three 0’s. This test case is not to be processed.

Output
For each test case, print in one line “YES” if the doggie can survive, or “NO” otherwise.

Sample Input

4 4 5
S.X.
..X.
..XD
….
3 4 5
S.X.
..X.
…D
0 0 0

Sample Output

NO
YES

题意:这个题目的意思是给定你起点S,和终点D,问你是否能在 T 时刻恰好到达终点D。
我采用dfs去做这个题。
令门开启的时间为T,某点到终点的奇偶性step=abs(xi-di)+abs(yj-dj); 已经花费的时间count
1.超界返回值0
2.遇墙返回(可以做预判)
3。剩下的时间不够 T-step《 t
4.奇偶剪枝
由题可以知道我们到达出口一定要走T步(门只在时间T时开启),我们在深搜的过程中判断从当前点到(xi,yi)到终点(di,dj)的距离S减最短距离step的奇偶性。由上的结论可知,只有当奇偶性为偶的时候才可以到终点
(T-count-step)&1
对这个位运算的说明:我们知道奇数的二进制末尾为1,偶数为0,1的二进制存储为1,那么按位与以后即可判断奇偶性。

下面贴ac代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#define  maxn 7

//迷宫
char b[maxn][maxn];
//规模,开启时间
int n,m,blood;
//快速往四个方向的偏移量
int dx[4]={-1,0,1,0};int dy[4]={0,1,0,-1};
//终点坐标
int bx,by;


int dfs( int x,int y ,int xue){
//如果时间已经用完
    if(xue<0){
        return 0;
    }
//判断是否刚好到达出口
    if(b[x][y]=='D'&&xue==0){
          return 1;
        else
            return 0;
    }
    else{
        //剪枝 判断是否可以到达 位运算
        int temp=xue-abs(x-bx)+abs(y-by);
        if(temp<0||temp&1)
            return 0;
         b[x][y]='X';//假设已经走过
         //往四个方向深搜
         for(int i=0;i<4;i++){
            int nx=x+dx[i];int ny=y+dy[i];
            //做超界处理, 做下一个位置的预判
            if(0<=nx&&nx<n&&0<=ny&&ny<m&&(b[nx][ny]=='.'||b[nx][ny]=='D')){
                if(dfs(nx,ny,xue-1)){
                    return 1;
                }
            }
         }
        b[x][y]='.';//回溯
    }
    return 0;
}


int main(){
    while(scanf("%d%d%d",&n,&m,&blood)!=EOF){
        if(n==0&&m==0&&blood==0)
         break;
        memset(b,0,sizeof(b));
        char temp[10];
        int x, y;
        iss=0;
        for(int i=0;i<n;i++){
            scanf("%s",temp);
            for(int j=0;j<m;j++){
                b[i][j]=temp[j];//防止开始搜索就挂掉
                if(temp[j]=='S'){
                    x=i;y=j;
                }
                if(temp[j]=='D'){
                    bx=i;by=j;
                }
            }
        }
        if(dfs(x,y,blood))
            printf("YES\n");
        else
            printf("NO\n");
    }
return 0;
}

最后说一句:今天是情人节,单身狗被虐就不说了,还被题目虐,伤上加伤让我怎么活啊。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值