zoukankan      html  css  js  c++  java
  • hdu Tempter of the Bone (奇偶剪枝)

    学习链接:http://www.ihypo.net/1554.html

    https://www.slyar.com/blog/depth-first-search-even-odd-pruning.html

    http://blog.csdn.net/chyshnu/article/details/6171758

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010

    题解:刚开始写直接超时,还没学剪枝,奇偶剪枝...

    关于奇偶剪枝

    首先举个例子,有如下4*4的迷宫,'.'为可走路段,'X'为障碍不可通过

    S...
    ....
    ....
    ...D

    从S到D的最短距离为两点横坐标差的绝对值+两点纵坐标差的绝对值 = abs(Sx - Dx) + abs(Sy - Dy) = 6,这个应该是显而易见的。

    遇到有障碍的时候呢

    S.XX
    X.XX
    ...X
    ...D

    你会发现不管你怎么绕路,最后从S到达D的距离都是最短距离+一个偶数,这个是可以证明的

    而我们知道:

    奇数 + 偶数 = 奇数
    偶数 + 偶数 = 偶数

    因此不管有多少障碍,不管绕多少路,只要能到达目的地,走过的距离必然是跟最短距离的奇偶性是一致的。

    所以如果我们知道从S到D的最短距离为奇数,那么当且仅当给定的步数T为奇数时,才有可能走到。如果给定的T的奇偶性与最短距离的奇偶性不一致,那么我们就可以直接判定这条路线永远不可达了。

    这里还有个小技巧,我们可以使用按位与运算来简化奇偶性的判断。我们知道1的二进制是1,而奇数的二进制最后一位一定是1,而偶数的二进制最后一位一定是0。所以如果数字&1的结果为1,那么数字为奇数,反之为偶数。

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <math.h>
     4 #include <limits.h> 
     5 #include <algorithm>
     6 #include <iostream>
     7 #include <ctype.h>
     8 #include <iomanip>
     9 #include <queue>
    10 #include <stdlib.h>
    11 using namespace std;
    12 
    13 char map[10][10];
    14 int flag, Xnum, Sx, Sy, Dx, Dy;
    15 int n, m, t;
    16 int dx[4] = {0,0,1,-1};
    17 int dy[4] = {1,-1,0,0};
    18 
    19 void DFS(int x, int y, int time)
    20 {
    21     if (x<=0 || x>n || y<=0 || y>m) return;
    22     if (flag == 1) return;  
    23     if (x == Dx && y == Dy && time == t)
    24     {
    25         if(time == t)
    26             flag = 1;
    27         return;
    28     }
    29 
    30     int temp=t-time-abs(x-Dx)-abs(y-Dy);
    31     if(temp<0||temp%2)   return ;
    32 
    33     for (int i = 0; i<4; i++)
    34     {
    35         int x1 = x + dx[i];
    36         int y1 = y + dy[i];
    37         if (map[x1][y1] != 'X')
    38         {
    39             map[x1][y1] = 'X';
    40             DFS(x1, y1, time + 1);
    41             map[x1][y1] = '.';
    42         }
    43     }
    44     return;
    45 }
    46 
    47 
    48 int main()
    49 {
    50     while (cin>>n>>m>>t)
    51     {
    52         if(n==0&&m==0&&t==0) break;
    53         Xnum = 0;
    54         for (int i = 1; i<=n; i++)
    55         {
    56             for (int j = 1; j<=m; j++)
    57             {
    58                 cin>>map[i][j];
    59                 if (map[i][j] == 'S')
    60                 {
    61                     Sx = i;
    62                     Sy = j;
    63                 }
    64                 if (map[i][j] == 'D')
    65                 {
    66                     Dx = i;
    67                     Dy = j;
    68                 }
    69                 if (map[i][j] == 'X')
    70                     Xnum ++;
    71             }
    72         }
    73         flag = 0;
    74         map[Sx][Sy] = 'X';
    75 
    76         if(n*m-Xnum<=t){
    77             cout<<"NO"<<endl;
    78             continue;
    79         }
    80         DFS(Sx, Sy, 0);
    81         if (flag)
    82             cout<<"YES"<<endl;
    83         else 
    84             cout<<"NO"<<endl;
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    一个非常简单的IMPDP事儿
    在线修改redo日志大小
    OGG-02803 Encountered a Data Guard role transition
    Linux新加磁盘挂载和重启自动挂载
    ORACLE字符集修改ORA-02374ORA-12899ORA-02372
    oracle nid修改dbname
    python模块PIL-获取带噪点噪线的随机验证码
    mysql两个重要的日志redolog和binlog
    在Spring中使用数据验证组件hibernate-validator
    SpringMVC接收请求参数所有方式总结
  • 原文地址:https://www.cnblogs.com/wangmengmeng/p/5099182.html
Copyright © 2011-2022 走看看