zoukankan      html  css  js  c++  java
  • 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
    ");
                continue;
            }
            ans=dfs(xx,yy,0);
            if(ans)
            {
                printf("YES
    ");
            }
            else
            {
                printf("NO
    ");
            }
        }
        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
    ");
            }
            else
            {
                memset(vis,0,sizeof(vis));
                step[x1][x2]=0;
                vis[x1][x2]=1;
                int ans=dfs(x1,x2);
                if(ans==1)
                {
                    printf("YES
    ");
                }
                else
                {
                    printf("NO
    ");
                }
            }
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    bzoj3223: Tyvj 1729 文艺平衡树
    bzoj1014: [JSOI2008]火星人prefix
    bzoj3231: [Sdoi2008]递归数列
    bzoj2282: [Sdoi2011]消防
    bzoj3195: [Jxoi2012]奇怪的道路
    成员内部类 局部内部类 匿名内部类
    静态代码块 构造代码块
    父类子类转换
    clone()方法
    后缀表达式求值
  • 原文地址:https://www.cnblogs.com/qioalu/p/4905579.html
Copyright © 2011-2022 走看看