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;
} 

 

posted @ 2016-05-25 18:57  Miller_S  阅读(334)  评论(0编辑  收藏  举报