zoukankan      html  css  js  c++  java
  • HDU1010 Tempter of the Bone(回溯 + 剪枝)

    本文链接:http://i.cnblogs.com/EditPosts.aspx?postid=5398734

    题意:

      输入一个 N * M的迷宫,这个迷宫里'S'代表小狗的位置,'X'代表陷阱,‘D’代表门,‘.’代表可行走的地方,小狗每次可以选择往周围的四个方向行走,问这个小狗能否正好T步找到门。

    思路:

      利用回溯 + 剪枝,这道题剪枝特别重要。

    剪枝一:

    可以把图看成这样:

    1 0 1 0 1
    0 1 0 1 0
    1 0 1 0 1
    0 1 0 1 0
    1 0 1 0 1

    则假设从点 a(i + j,横纵坐标之和) 走到点 b(i + j) ,如果 a 和 b 的奇偶性相同,那么从 a 到 b 必须是偶数步.如果 a  和 b 的奇偶性不同则走过的步数必须是奇数步。所以 当 (a + b + T)为奇数时一定不能恰好到达。

    剪枝二:

    如果已经找到答案就没有要继续求解。

    剪枝三:

    T大于从S到D的最长路径,小于从S到D的最短路径,则无解。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 11;
    char Gra[MAXN][MAXN];
    int stepX[] = {0, 0, 1, -1};
    int stepY[] = {-1, 1, 0, 0};
    int N, M, T;
    int cnt;
    int beginX, beginY, endX, endY;
    int OK;
    
    int check(int x, int y)
    {
        if(Gra[x][y] == 'O')  return 0;   // 走到了已经走过的路
        if(Gra[x][y] == '*')  return 0;   //走出了边界
        if(Gra[x][y] == 'X')  return 0;    //走到了墙
        if(cnt > T)           return 0;  //在此时走的步数已经大于总步数则
                              return 1;
    }
    
    void backtrack(int x, int y)
    {
        if(x == endX && y == endY ) //到达终点
        {
           if(cnt == T)          //找到了答案
               OK = 1;
        }
        else
        {
            for(int i = 0; i < 4; i++)  //在这点一共有四种选择(状态)
            {
                int tx =  x + stepX[i];
                int ty =  y + stepY[i];
                if(check(tx, ty))    //检查所选择的状态是否合理
                {
                    ++cnt;              //记录走过的步数
                    Gra[tx][ty] = 'O';   //标记走过的地方
                    if(OK) return;    //尤为重要的剪枝 ,如果找到答案,就不用继续递归,
                    backtrack(tx, ty);
                    Gra[tx][ty] = '.';  //恢复现场
                    --cnt;
    
                }
            }
        }
    }
    
    int main()
    {
        //freopen("in.txt","r", stdin);
        while(~scanf("%d%d%d",&N, &M, &T) && N)
        {
            getchar();
            beginX = beginY =  endX = endY = 0;
            memset(Gra, '*', sizeof(Gra));
            for(int i = 1; i <= N; i++)
            {
                for(int j = 1; j <= M; j++)
                {
                    scanf("%c",&Gra[i][j]);
                    if(Gra[i][j] == 'S')
                        beginX = i, beginY = j;
                    if(Gra[i][j] == 'D')
                        endX = i, endY = j;
                }
                getchar();
            }
            OK = 0;
            if( (T > M * N) || ( T < (abs(beginX - endX) + abs(beginY - endY)) ) || ( (beginX + beginY + endX + endY + T) & 1 ))//剪枝二、三
            {
                printf("NO
    "); continue;
            }
            cnt = 0;
            Gra[beginX][beginY] = 'O';
            backtrack(beginX, beginY);
            if(OK) printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    数字图像处理(一)之灰度转换和卷积python实现
    ArcEngine+C# 森林资源仿真系统 核心代码
    Dijkstra和Floyd算法遍历图的核心
    python像操作文件一样操作内存的模块 StringIO
    python操作Redis方法速记
    python中时间处理标准库DateTime加强版库:pendulum
    utittest和pytest中mock的使用详细介绍
    《金字塔原理》 读书笔记
    python轻量级orm框架 peewee常用功能速查
    docker中安装的mysql无法远程连接问题解决
  • 原文地址:https://www.cnblogs.com/Ash-ly/p/5398734.html
Copyright © 2011-2022 走看看