HDU 1010

题意:一只狗(柴犬,看到一块骨头,迷失在了maze里,S是起点,D是终点,问你能不能在时间T时从起点到达终点.

这题有个小trick: 奇偶剪枝+普通剪枝

解释一下:

普通剪枝:从S到D要走的步数是k=abs(x1-x2)+abs(y1-y2);那么如果k>=T,永远不可能到达;

奇偶剪枝:

首先,分析一下两个坐标的奇偶性与K的关系

当坐标是奇数的时候: x,y一定是一奇一偶的关系(妈哒输入法好难用

当坐标是偶数的时候:x,y一定全为奇数或者全为偶数.

当两个坐标奇偶性一样的时候:

1.全为奇数,那么K=(奇数-奇数)+(偶数-偶数)或者K=(奇数-偶数)+(偶数-奇数);

众所周知:

奇数+/-奇数=偶数;

偶数+/-偶数=偶数;

奇数+/-偶数=奇数;

妈哒这些数数好复杂!

所以当两个坐标全为奇数时K=(奇数-奇数)+(偶数-偶数)或者K=(奇数-偶数)+(偶数-奇数)=偶数+偶数或者K=奇数+奇数;

总而言之的言之:当两个坐标都是奇时,K=偶数;

2.全为偶数是

K=(奇数-奇数)+(奇数-奇数)=偶数;

或者K=(偶数-偶数)+(偶数-偶数)=偶数;

或者K=(奇数-偶数)+(奇数-偶数)=偶数;

卧槽怎么写出原理这么多,快出来个人告诉我简便证法!!!

反正总而言之!!!

上面的都是草泥马写的!!不用看了!!

当两个坐标奇偶性相同时,需要走的步数一定绝壁是:偶数!

当两个坐标的奇偶性不一样的时候:

这就简单了:其中一个一定是一奇一偶;另一个要么全是奇,要么全是偶;

所以K=(奇数-奇数)+(奇数-偶数)或者K=(奇数-偶数)+(偶数-偶数)

当两个坐标奇偶性不相等时,需要走的步数K都等于奇数!

 

好了好了,累死我了;

说了这么多,其实就是一个奇偶剪枝的结论:

当两个坐标奇偶性相等时,需要走偶数步!

当两个坐标奇偶性不相等时,需要走奇数步!

 

翻译成C语言就是:

if((x1+y1+x2+y2)%2==0)

{

     两个坐标奇偶性相等;

}

if((x1+y1+x2+y2)%2==1)

{

      两个坐标奇偶性不相等;

}

要想奇偶性相等的时候T是偶数;

奇偶性不想等的时候T是奇数;


只需要把上面这么一大坨的东西变成一句话(哭

if((x1+y1+x2+y2+T)%2==0)

 

AC代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int dx[4]= {1,0,-1,0};
const int dy[4]= {0,1,0,-1};
char s[56][56];
int n,m,t,xxx,yyy;
int vis[105][56];

int dfs(int x,int y,int cnt)
{
    int k;
    for(int i=0; i<4; i++)
    {
        int x1=x+dx[i];
        int y1=y+dy[i];
        if(x1>=0&&x1<n&&y1>=0&&y1<m&&vis[x1][y1]==0)
        {
            if(s[x1][y1]=='.')//如果遇到"."继续往下搜
            {
                vis[x1][y1]=1;
                k=dfs(x1,y1,cnt+1);
                if(k==1)
                {
                    return 1;
                }
                vis[x1][y1]=0;
            }
            else if(s[x1][y1]=='D')
            {
                if(cnt+1==t)
                {
                    return 1;
                }
                else if(cnt+1>t)
                {
                    return 0;
                }
            }
        }
    }
    return 0;
}
int main()
{
    int xx,yy;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        memset(vis,0,sizeof(vis));
        if(n==0&&m==0&&t==0)
        {
            break;
        }
        for(int i=0; i<n; i++)
        {
            scanf("%s",s[i]);
        }
        int ans=0;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(s[i][j]=='S')
                {
                    xx=i;
                    yy=j;
                }
                else if(s[i][j]=='D')
                {
                    xxx=i;
                    yyy=j;
                }
            }
        }
        if(abs(xx-xxx)+abs(yy-yyy)>t||(xx+yy+xxx+yyy+t)%2==1)//普通剪枝+奇偶剪枝
        {
            printf("NO\n");
            continue;
        }
        ans=dfs(xx,yy,0);
        if(ans)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}
View Code

 第二次做,再来一份代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
int sx[4]= {1,-1,0,0};
int sy[4]= {0,0,-1,1};
int n,t,step[15][15],m,vis[15][15];
char s[15][15];

int dfs(int x,int y)
{
    if(s[x][y]=='D'&&step[x][y]==t)
    {
        return 1;
    }
    if(s[x][y]=='.'||s[x][y]=='S')
    {
        for(int i=0; i<4; i++)
        {
            int kk1=x+sx[i];
            int kk2=y+sy[i];
            if(kk1>=0&&kk1<n&&kk2>=0&&kk2<m&&vis[kk1][kk2]==0)
            {
                vis[kk1][kk2]=1;
                step[kk1][kk2]=step[x][y]+1;
                int kk=dfs(kk1,kk2);
                if(kk==1)
                {
                    return 1;
                }
                vis[kk1][kk2]=0;
            }
        }
    }
    return 0;
}
int main()
{
    int x1,x2,k1,k2;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        if(n==0&&m==0&&t==0)
        {
            break;
        }
        for(int i=0; i<n; i++)
        {
            scanf("%s",s[i]);
            for(int j=0; j<m; j++)
            {
                if(s[i][j]=='S')
                {
                    x1=i;
                    x2=j;
                }
                else if(s[i][j]=='D')
                {
                    k1=i;
                    k2=j;
                }
            }
        }
        if((x1+x2+k1+k2+t)%2!=0||fabs(x1-x2)+fabs(k1-k2)>t)
        {
            printf("NO\n");
        }
        else
        {
            memset(vis,0,sizeof(vis));
            step[x1][x2]=0;
            vis[x1][x2]=1;
            int ans=dfs(x1,x2);
            if(ans==1)
            {
                printf("YES\n");
            }
            else
            {
                printf("NO\n");
            }
        }

    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/qioalu/p/4905579.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值