zoukankan      html  css  js  c++  java
  • hdu-1010 dfs+剪枝

    思路:

    剪枝的思路参考博客:http://www.cnblogs.com/zibuyu/archive/2012/08/17/2644396.html  在其基础之上有所改进

    题意可以给抽象成给出一个图,让你求S点到D点之间是否存在一条长度为T的道路。求两地之间的距离用的是dfs,而dfs在这里的关键是找到回溯的条件,就是当到达D点并且剩余步数为0时,则符合题意的要求,由于我们只需要知道这样一条长度为T的路径是否存在,因此当我们发现存在的时候,只需要将一个全局flag给设置为1即可,然后从此之后的所有dfs调用都直接return。

    另外关键的问题就是剪枝。当我们的思路走到求两个点的距离时,我们应当“俯视”一下——这两个点S和D,他们之间的距离从整个图上来看有什么性质。在这里有这样的规律:

    也就是一开始给我们的两个起始点S和D,如果他们之间距离的最小值的奇偶性和T的奇偶性是不同的,那么在一开始我们就可以判断——“NO”!因为0->0和1->1无论怎么走需要的步数都为偶数步,1->0或0->1无论怎么走需要的步数都为奇数步。利用这点,从一开始我们就可以进行奇偶剪枝。

    还有一个并不影响最后AC但是也值得思考的一个剪枝,就是在一开始的时候给定图可走的点数就小于T,那就直接不需要考虑。


    代码:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    char G[10][10];//G[n][m]
    int dx,dy;
    int n,m,t;
    int dir[4][2] = {{0,-1},{0,1},{1,0},{-1,0}};
    int flag;
    
    void dfs(int cx,int cy,int step) {
        //now we're at (cx,cy),there're "step" steps left to get to (dx,dy)
        if(cx<1||cx>n||cy<1||cy>m)
            return;
        if(flag) return;
        if(cx==dx&&cy==dy&&step==0) {
            flag = 1;
            return ;
        }
        for(int i = 0;i < 4;i++) {
            int nx = cx+dir[i][0];
            int ny = cy+dir[i][1];
            if(nx<1||ny<1||nx>n||ny>m) continue;//(1)over-border
            if(G[nx][ny] == 'X') continue;//(2)can't get to(nx,ny)
            G[cx][cy] = 'X';
            dfs(nx,ny,step-1);
            if(flag) return;
            G[cx][cy] = '.';
        }
    }
    
    int main()
    {
        int sx,sy;
        int i,j;
        while(scanf("%d%d%d",&n,&m,&t)&&(n!=0||m!=0||t!=0)) {
            int wall = 0;
            for(i=1;i<=n;++i)
            {
                scanf("%s",G[i]+1);
                for(j=1;j<=m;++j)
                {
                    if(G[i][j]=='S')
                    {
                        sx=i;
                        sy=j;
                    }
                    if(G[i][j]=='D')
                    {
                        dx=i;
                        dy=j;
                    }
                    if(G[i][j]=='X') wall++;
                }
            }
            //cut branches-1
            if((abs(sx-dx)+abs(sy-dy))%2 != t%2) {
                cout<<"NO"<<endl;
                continue;
            }
            //cut branches-2
            if(n*m-wall < t) {
                cout<<"NO"<<endl;
                continue;
            }
            flag = 0;
            dfs(sx,sy,t);
            if(flag) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    } 
  • 相关阅读:
    Razor 常用又容易忘记语法
    游览器 reflow
    正则表达式
    migration to end point routing
    js 翻译 c# 注意事项
    Angular 学习笔记 work with excel (导出 excel)
    html4,5 basic
    IIS 服务器配置
    meta 的用途
    正则表达 常用
  • 原文地址:https://www.cnblogs.com/immortal-worm/p/5528135.html
Copyright © 2011-2022 走看看