HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)

题意:从S走到D,D只有在t时会开,走过的点不能再访问,问是否能在t时走到D
挺BFS套路的题。。但是为了训练DFS的思想所以用DFS进行求解了~

首先记录S和D的位置(sx,sy)(ex,ey)
从(sx,sy)开始dfs,设初始时刻为0
将访问过的点设为’X’,D在非t时刻都为’O’
从每个点的上下左右方向中有’.’的位置分别dfs,并且在有’O’的位置判断下一时刻是否为t,是则说明能到达
每次访问完一种情况后将访问点再重置为’.’

然后是剪枝:
如果已经可以到达,则不再继续dfs;
然后用奇偶剪枝优化:
某位置(x,y)到(ex,ey)的最小路程长度是(abs(x-ex)+abs(y-ey)),并且如果中间有障碍物绕开时,一定是增加偶数个(可以是0个):





↓ → → →D


↓ →
X ↓
←↓
↓ → → →D
(2个)


↓ →
X ↓
 ↓
 → → →D
(0个)

因此如果当前点能到达D,那么它们的距离(abs(x-ex)+abs(y-ey))+偶数步=剩下来的时间(t-time)
因此如果 (t-time)-(abs(x-ex)+abs(y-ey))为奇数,则一定不能到达,直接return

最后打印结果即可~

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=10;
int n,m,t,ans=0;
int sx,sy,ex,ey;
char maze[N][N];
int flag=0;
void dfs(int x,int y,int time){

    if(flag) return;
    int temp=(t-time)-(abs(x-ex)+abs(y-ey));//奇偶剪枝
    if(temp<0||temp&1) return;

    if(time==t){
        maze[ex][ey]='D';
    }
    else{
        maze[ex][ey]='O';
    }

    maze[x][y]='X';

    for(int dy=-1;dy<=1;dy++){
            int ny=y+dy;
            if(ny>=0&&ny<m){
                if(maze[x][ny]=='O'&&time+1==t){
                    flag=1;
                    return;
                }
                else if(maze[x][ny]=='.'){
                        dfs(x,ny,time+1);
                        maze[x][ny]='.';
                }

            }

    }
    for(int dx=-1;dx<=1;dx++){
        int nx=x+dx;
        if(nx>=0&&nx<n){
            if(maze[nx][y]=='O'&&time+1==t){
                flag=1;
                return;
            }
            if(maze[nx][y]=='.'){
                dfs(nx,y,time+1);
                maze[nx][y]='.';
            }       
        }   
    }


}
int main(){
    while(~scanf("%d %d %d",&n,&m,&t)&&n&&m&&t){
        flag=0;
        getchar();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%c",&maze[i][j]);
                if(maze[i][j]=='S'){
                    sx=i;sy=j;
                }
                else if(maze[i][j]=='D'){
                    ex=i;ey=j;
                }
            }
            getchar();
        }
        dfs(sx,sy,0);

        flag?puts("YES"):puts("NO");
    }
}
/*
2 3 3
S.X
..D
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值