hdu1010---Tempter of the Bone

开始想着用广搜写写,后来想想感觉就是自己给自己找不自在,没法写。然后又开始用深搜来做,以前虽然学过深搜,但是好久没写,手很生,但是还是经过一番推理后写出来了,很开心。结果果断交上去就TLE了,后来想想应该可以剪枝吧,于是就剪枝,只是剪掉了输入的'.'少于那个规定时间t-1的情况,交上去又TEL了,剪得不够完美,准备继续剪,但是后来的剪枝结果证明都是不够完美的,于是果断百度了方法,发现了一种很神奇的方法就是奇偶剪枝,如下图

这就是传说中的奇偶剪枝,意思就是说1---1,0---0都是需要偶数步的,1---0,0---1都是需要奇数步的,这么就可以根据当前所剩步数的奇偶性跟当前位置和终点的奇偶性共同判断是否能走通。好深奥的说。

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
char Map[10][10];
bool vis[10][10];
int f[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};
int n,m,t;
bool flag1=0;
struct node
{
    int x,y,value;
    node()
    {
        x=1;
        y=1;
        value=1;
    }
};
node a,b;
void init()
{
    flag1=0;
    for(int i=0; i<10; i++)
    {
        for(int j=0; j<10; j++)
        {
            vis[i][j]=0;
            Map[i][j]='#';
        }
    }
    a.value=t+1;        //排除没起点的情况
}
bool dfs(node tmp)
{
    bool flag,flag2;
    if(tmp.value>t)     //剪枝
        return 0;
    //  cout<<"tmp "<<tmp.x<<" "<<tmp.y<<" "<<tmp.value<<endl;
    if(tmp.x==b.x&&tmp.y==b.y&&tmp.value==t)
    {
        //   cout<<"gg"<<endl;
        return 1;
    }
    flag=(t-tmp.value)%2;   //判断所剩步数的奇偶性
    vis[tmp.x][tmp.y]=1;    //标记走到当前位置
    for(int i=0; i<4; i++)
    {
        a.x=tmp.x+f[i][0];
        a.y=tmp.y+f[i][1];
        a.value=tmp.value+1;
        if(Map[a.x][a.y]!='X'&&a.x>=1&&a.y>=1&&a.x<=n&&a.y<=m&&vis[a.x][a.y]==0)
        {
            //递归的条件
            //  cout<<a.x<<" "<<a.y<<" "<<a.value<<endl;
            flag2=(tmp.x+tmp.y)%2;  //判断当前位置的奇偶性
            if(flag2!=flag1&&flag==1||flag2==flag1&&flag==0)
            {
                //奇偶剪枝,如果满足当前位置跟终点位置奇偶性不同且所剩步数为奇
                //或者当前位置跟终点位置奇偶性相同且所剩步数为偶就往下递归
                //     cout<<flag1<<"* "<<flag2<<"* "<<flag<<endl;
                bool FG=0;
                FG=dfs(a);
                if(FG)
                    return 1;
            }
        }
    }
    vis[tmp.x][tmp.y]=0;    //恢复标记
    return 0;
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&t)!=EOF&&n!=0&&m!=0&&t!=0)
    {
        int num=0;
        getchar();
        init();
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                scanf("%c",&Map[i][j]);
                if(Map[i][j]=='.')
                {
                    num++;
                }
                else if(Map[i][j]=='S')
                {
                    a.x=i;
                    a.y=j;
                    a.value=0;
                }
                else if(Map[i][j]=='D')
                {
                    b.x=i;
                    b.y=j;
                    flag1=(i+j)%2;  //判断终点的奇偶性
                }
            }
            getchar();
        }
        if(num<t-1)         //根据.的数量剪枝
        {
            printf("NO\n");
            continue;
        }
        bool ans=dfs(a);
        if(ans)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}





/*
4 4 5
S.X.
..X.
.D..
XXXX
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值