zoukankan      html  css  js  c++  java
  • 51 nod 1522 上下序列——序列dp

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1522

    很好的思想。考虑从小到大一对一对填数,这样也能对它的大小限制做一些操作了。

    因为从小到大,所以只能全填在左边、全填在右边、两边各填一个。记录左边填到了哪个位置,就可知右边填到了哪个位置。转移之前判断一下这样填是否合法即可。

    新的不合法的状态只会和现在填的两个位置有关。

    注意输入格式!!符号前后有空格!!!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=40,M=105;
    int n,m,x[M],y[M],sgn[M],tx,ty;
    ll dp[N][N<<1],ans;
    char ch[20];
    bool check(int p0,int p1,int r,int fx)
    {
        //printf("p0=%d p1=%d r=%d fx=%d
    ",p0,p1,r,fx);
        for(int i=1;i<=m;i++)
            if(sgn[i]==0&&
               ( ( (x[i]==p0||x[i]==p1)&&y[i]!=p0&&y[i]!=p1)||
                 ( (y[i]==p0||y[i]==p1)&&x[i]!=p0&&x[i]!=p1) ) )
                return 0;//以前都合法,不合法仅出现在p0、p1位置上
        if(!fx)
        {
            for(int i=1;i<=m;i++)
            {
                //printf("sgn[%d]=%d
    ",i,sgn[i]);
                if(sgn[i]==1||sgn[i]==2)
                {
                    tx=x[i];ty=y[i];
                    if(sgn[i]==2)swap(tx,ty);
                    //printf("tx=%d ty=%d p0=%d p1=%d r=%d
    ",tx,ty,p0,p1,r);
                    if((ty==p0||ty==p1)&&tx>=p0&&tx<r) return 0;
                }
                if(sgn[i]==3||sgn[i]==4)
                {
                    tx=x[i];ty=y[i];
                    if(sgn[i]==4)swap(tx,ty);
                    if((ty==p0||ty==p1)&&tx>p1&&tx<r) return 0;
                }
            }
        }
        if(fx==1)
        {
            for(int i=1;i<=m;i++)
            {
                if(sgn[i]==1||sgn[i]==2)
                {
                    tx=x[i];ty=y[i];
                    if(sgn[i]==2)swap(tx,ty);
                    if((ty==p0||ty==p1)&&tx<=p1&&tx>r) return 0;
                }
                if(sgn[i]==3||sgn[i]==4)
                {
                    tx=x[i];ty=y[i];
                    if(sgn[i]==4)swap(tx,ty);
                    if((ty==p0||ty==p1)&&tx<p0&&tx>r) return 0;
                }
            }
        }
        if(fx==2)
        {
            for(int i=1;i<=m;i++)
            {
                if(sgn[i]==1||sgn[i]==2)
                {
                    tx=x[i];ty=y[i];
                    if(sgn[i]==2)swap(tx,ty);
                    if((ty==p0||ty==p1)&&tx>=p0&&tx<=p1) return 0;
                }
                if(sgn[i]==3||sgn[i]==4)
                {
                    tx=x[i];ty=y[i];
                    if(sgn[i]==4)swap(tx,ty);
                    if((ty==p0||ty==p1)&&tx>p0&&tx<p1) return 0;
                }
            }
        }
        return 1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);ch[0]=getchar();
        while(ch[0]!='
    ')ch[0]=getchar();
        for(int i=1,len=0,j;i<=m;i++,len=0)
        {
            ch[++len]=getchar();
            while(ch[len]!='
    ')ch[++len]=getchar();
            for(j=1;j<len;j++)
            {
                if(ch[j]>='0'&&ch[j]<='9')
                    x[i]=(x[i]<<3)+(x[i]<<1)+ch[j]-'0';
                else break;
            }
            while(ch[j]==' ')j++;
            //printf("j=%d chj=(%c)
    ",j,ch[j]);
            if(ch[j]=='=') sgn[i]=0,j++;
            else if(ch[j]=='<'&&ch[j+1]=='=')sgn[i]=3,j+=2;
            else if(ch[j]=='>'&&ch[j+1]=='=')sgn[i]=4,j+=2;
            else if(ch[j]=='<')sgn[i]=1,j++;
            else if(ch[j]=='>')sgn[i]=2,j++;
            while(ch[j]==' ')j++;
            //printf("j=%d chj=(%c)
    ",j,ch[j]);
            for(;j<len;j++)
                y[i]=(y[i]<<3)+(y[i]<<1)+ch[j]-'0';
            //printf("x=%d sgn=%d y=%d
    ",x[i],sgn[i],y[i]);
        }
        dp[0][0]=1;
        for(int i=0,lm;i<n;i++)
        {
            lm=(i<<1);
            for(int j=0,r;j<=lm;j++)
            {
                //if(dp[i][j])printf("dp[%d][%d]=%lld
    ",i,j,dp[i][j]);
                r=(n<<1)-(lm-j)+1;
                if(check(j+1,j+2,r,0))
                    dp[i+1][j+2]+=dp[i][j];
                        //printf("dp[%d][%d]=%lld(%d,%d)
    ",i+1,j+2,dp[i+1][j+2],i,j);
                if(check(r-2,r-1,j,1))
                    dp[i+1][j]+=dp[i][j];
                //printf("dp[%d][%d]=%lld(%d,%d)
    ",i+1,j,dp[i+1][j],i,j);
                if(check(j+1,r-1,0,2))
                    dp[i+1][j+1]+=dp[i][j];
                        //printf("dp[%d][%d]=%lld(%d,%d)
    ",i+1,j+1,dp[i+1][j+1],i,j);
            }
        }
        int lm=(n<<1);
        for(int j=0;j<=lm;j++) ans+=dp[n][j];
        printf("%lld
    ",ans/3);
        return 0;
    }
  • 相关阅读:
    0-1 RSS订阅
    4-1 文件管理
    3-2 LInux文件管理
    解决docker容器开启端口映射后,会自动在防火墙上打开端口的问题
    samba服务的基本配置
    ftp服务的基本配置
    Linux-Bash终端快捷键
    对systemV和systemd的简单理解(服务方面)
    分析FAT32内部结构-入门篇-
    分享一下今天遇到的两个问题,一个是关于C语言内存泄漏问题,另一个是关于Linux下grep使用时的问题
  • 原文地址:https://www.cnblogs.com/Narh/p/9672719.html
Copyright © 2011-2022 走看看