• hdu1010 Tempter of the Bone---DFS+奇偶剪枝


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=1010

    题目描述:
    根据地图,'S'为开始位置,'D'为门的位置,' . '为空地,'X'为墙,不能经过,问:在指定的时间,是否能到达'门'的位置。注意:路不可以重复经过,时间也要刚好是 t ,不能少.

    思路:

    此处不能用BFS,因为时间要恰好为t,还是得用DFS,不过需要剪枝才能过。

    奇偶剪枝:

    从一个点到达另外一个点的最短路径长度(时间)可以根据两点坐标求出,路径长度(非最短)与最短路径的长度同奇偶,它们的差一定是偶数!举个例子,就像两个偶数的差差是偶数,两个个数的差也是偶数.

    此处还有一个剪枝:
    设墙的数目为wall,如果wall + t >= n * m,一定到达不了,因为大于号显然成立,这里主要讨论等号的情况。

    比如下图

    3 3 1

    SDX

    XXX

    XXX

    只需要一步就可以到达,此时wall = 7, t = 1,wall + t < n * m,有可行解,这是由于有S,D的存在,所以如果有可行解,wall的数目一定会比n*m-t要小,等于的话是没有可行解的。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<string>
     6 #include<queue>
     7 using namespace std;
     8 typedef long long ll;
     9 const int INF = 1<<30;
    10 const int maxn = 100000;
    11 int T, cases;
    12 int n, m, k, x1, y1, x2, y2;
    13 char Map[10][10];
    14 int dir[4][2] = {0,1,1,0,-1,0,0,-1};
    15 bool dfs(int x, int y, int time)//到x1, y1点,花费时间time
    16 {
    17     if(x < 0 || x >= n || y < 0 || y >= m || time > k)return false;
    18     //剪枝
    19     if(time == k && x == x2 && y == y2)return true;
    20     int mintime = k - time - abs(x - x2) - abs(y - y2);
    21     if(mintime < 0)return false;//最优性剪枝,当前沿着最优路径走,还是会超过k秒,返回假
    22     if(mintime & 1)return false;//奇偶剪枝,相减的时间是奇数的话,在k秒的时候一定到不了终点
    23 
    24     for(int i = 0; i < 4; i++)
    25     {
    26         int xx = x + dir[i][0];
    27         int yy = y + dir[i][1];
    28         if(Map[xx][yy] != 'X')
    29         {
    30             Map[xx][yy] = 'X';
    31             if(dfs(xx, yy, time + 1))return true;
    32             Map[xx][yy] = '.';
    33         }
    34     }
    35     return false;
    36 }
    37 int main()
    38 {
    39     while(cin >> n >> m >> k && (n + m + k))
    40     {
    41         int wall = 0;
    42         for(int i = 0; i < n; i++)
    43         {
    44             cin >> Map[i];
    45             for(int j = 0; j < m; j++)
    46             {
    47                 if(Map[i][j] == 'S')x1 = i, y1 = j;
    48                 else if(Map[i][j] == 'D')x2 = i, y2 = j;
    49                 else if(Map[i][j] == 'X')wall++;
    50             }
    51         }
    52         if(wall + k >= n * m)
    53         ///这里是一个特别好的剪枝,如果墙的数目+步数>=n*m,一定不可能完成任务
    54         ///重点考虑等号,除了墙还有'S'和'D',墙的数目最多为n*m-k-1(距离,比如k = 1时,S和D相邻,其他都是墙,此时墙的数目最多为n*m-2,满足上述式子)
    55         {
    56             printf("NO
    ");
    57             continue;
    58         }
    59         Map[x1][y1] = 'X';//先设置成X表示该点不能再经过
    60         if(dfs(x1, y1, 0))printf("YES
    ");
    61         else printf("NO
    ");
    62     }
    63 }
  • 相关阅读:
    ListView
    Android 控件知识点
    Android之alertDialog、ProgressDialog
    Android 控件知识点,
    知晓当前是哪一个活动
    Activity的启动模式
    iOS9之Bitcode
    Xcode7免证书真机调试实践
    XCode6之后预编译文件的创建
    Swift计算文本宽高
  • 原文地址:https://www.cnblogs.com/fzl194/p/8678159.html
Copyright © 2020-2023  润新知