hdu 1010 Tempter of the Bone

这道题用到的方法是: DFS+奇偶剪枝+回溯
一般的DFS是不需要回溯的,仅仅做一个标记而已,但是这道题一个递归经历的,下次可以重用,所以需要回溯。
DFS深度优先遍历:就是循环+递归,循环是为了保证都能够有机会进行递归。递归就是深度有限的体现。

回溯:回溯是指当前递归搜索路径不满足条件时,但是还有其他未搜索路径,存在满足条件的可能性,需要返回起点重新搜索(回溯)。由于可能和当前路径某些点重复,所以回溯需要记得搜索后把状态回复到初始值。
剪枝:剪枝技术说白了,就是提前去除某些绝对不可能的情况,避免浪费时间,做明知道不可能的事,减少搜索条件,缩小搜索范围。这里奇偶剪枝意思就是把剩余步数和剩余距离的差的绝对值为奇数的条件剪掉。

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
bool mark[7][7];
int dpx,dpy;
int spx,spy;
int n=0,m=0,t=0;


int dix[]={-1,1,0,0};

int diy[]={0,0,-1,1};



int ABS(int x){
    return x<0?-x:x;
}

bool dfs(int i,int j,int step){

//stop condition step==t but not D
  if(step==t){

    if(mark[dpx][dpy])
        return true;
    else
        return false;
  }
  int tmp=ABS(i-dpx)+ABS(j-dpy)-ABS(step-t);
  //cut condition
  if(tmp>0||tmp%2!=0){
    return false;
  }
  // dfs
 for(int s=0;s<4;s++){

   int  ni=i+dix[s];
   int  nj=j+diy[s];

   if(ni<0||ni>=n||nj>=m||nj<0||mark[ni][nj]) continue;

   mark[ni][nj]=true;

    if(dfs(ni,nj,step+1)){
            return true;
    }

    mark[ni][nj]=false;

  }
    return false;
}


int main()
{
    //index of door and the start point
    string s;
    while(scanf("%d%d%d",&n,&m,&t)&&n){

        memset(mark,false,sizeof(mark));
        //input
        for(int i=0;i<n;i++){

            cin>>s;
            for(int j=0;j<m;j++){


              //record index of S and D;
                if(s[j]=='S'){
                    spx=i;
                    spy=j;
                    mark[i][j]=true;

                }else if(s[j]=='D'){
                    dpx=i;
                    dpy=j;
                }else if(s[j]=='X'){
                    mark[i][j]=true;
                }
                // TODO set mark[i][j]=true if  s[i][j]=='X'
            }
        }

        if(dfs(spx,spy,0)){
            printf("YES\n");
       }else{
       printf("NO\n");
      }

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值