zoukankan      html  css  js  c++  java
  • hdu 1010 Tempter of the Bone

    题目

    题意:

    根据地图,'S'为开始位置,'D'为门的位置,' . '为空地,'X'为墙,不能经过,

    问:在指定的时间,是否能到达'门'的位置.

    注意:路不可以重复经过,时间也要刚好是 t ,不能少.

    思路:用DFS,不能用BFS,因为BFS求的是最短路径,而此题的路径不一定最短.
    剪枝是关键,奇偶剪枝.

    奇偶剪枝原理:
    要理解奇偶剪枝,先了解一下曼哈顿距离,从一个点到达另外一个点的最短路径长度(时间)可以根据两点坐标求出,

    现假设起点为(sx,sy),终点为(ex,ey),起点到终点的最短步数=abs(ex-sx)+abs(ey-sy)],
    路径长度(非最短)与最短路径的长度同奇偶,它们的差一定是偶数!举个例子,就像两个偶数的差差是偶数,两个个数的差也是偶数.
    本题还有一个剪枝:n*m-wall与t的关系,wall为'X'的数量,解释一下,n*m为区域总数,所以m*n-wall<=t 一定不到到达终点

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    char mp[10][10];
    int n,m,t;
    int sx,sy,ex,ey;
    int dir[4][2]={0,1,1,0,0,-1,-1,0};
    int flag;
    
    void dfs(int x,int y,int time)
    {
        if(x<0||x>=n||y<0||y>=m)
            return;
        if(x==ex&&y==ey&&time==t)
        {
            flag = true;
            return;
        }
        //if(flag) return;
        int temp=(t-time)-(abs(x-ex)+abs(y-ey));//奇偶剪枝
        if(temp<0||temp&1) return;
        for(int i=0;i<4;i++)
        {
            int xx = x +dir[i][0];
            int yy = y +dir[i][1];
            if(mp[xx][yy]!='X')
            {
                mp[xx][yy]='X';
                dfs(xx,yy,time+1);
                mp[xx][yy]='.';
                if(flag) return;
            }
        }
    }
    
    int main()
    {
        while(cin>>n>>m>>t)
        {
            if(n==0&&m==0)
                break;
            int wall=0;
            for(int i=0;i<n;i++)//在输入的时候 记录起点和终点下标,墙的个数
            {
                for(int j=0;j<m;j++)
                {
                    cin>>mp[i][j];
                    if(mp[i][j]=='S')
                        sx = i,sy = j;
                    else if(mp[i][j]=='D')
                        ex = i,ey = j;
                    else if(mp[i][j]=='X')
                        wall++;
                }
            }
            //因为路不可以重复经过,时间要刚好,如果可以走的步数小于时间,那一定在t时间走不出去
            if(n*m-wall<=t)
            {
                cout<<"NO"<<endl;
                continue;
            }
            flag = false;
            mp[sx][sy]='X';
            dfs(sx,sy,0);
            if(flag) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }
    

    dfs的题做起来始终不太顺手,因为要用到递归,递归就要知道子问题到底需要哪些参数,以及回溯过程中需要复原哪些数。

  • 相关阅读:
    智慧养老民政监管平台建设方案
    CF600E Lomsat gelral dsu on tree
    dsu on tree详解
    【Spring 从0开始】Spring5 新功能,整合日志框架 Log4j2
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 数据库事务参数
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 操作数据库
    【Spring 从0开始】AOP 操作
    【Spring 从0开始】AOP 操作中的相关术语、环境准备
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160193.html
Copyright © 2011-2022 走看看