zoukankan      html  css  js  c++  java
  • 51Nod 1522 上下序列 —— 区间DP

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

    区间DP,从大往小加;

    新加入一种数有3种加法:全加左边,全加右边,一左一右;

    然后判断一下加完是否满足那些条件即可;

    但判断这个条件还挺复杂,一不小心就写丑了错了...

    冗余错误写法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int n,m,c[105][3];
    ll f[40][80][80];
    char ch[5];
    bool ck(int a,int b,int fl)
    {
        if(fl==1)
        {
            for(int i=1,x,y;i<=m;i++)
            {
                x=c[i][1]; y=c[i][2];
                if((x==a&&y==b)||(x==b&&y==a)&&c[i][0]!=1)return 0;
                if((x==a||x==b)&&y>b&&(c[i][0]!=4&&c[i][0]!=2))return 0;
                if((y==a||y==b)&&x>b&&(c[i][0]!=5&&c[i][0]!=3))return 0;
            }
            return 1;
        }
        if(fl==0)
        {
            for(int i=1,x,y;i<=m;i++)
            {
                x=c[i][1]; y=c[i][2];
                if((x==a&&y==b)||(x==b&&y==a)&&c[i][0]!=1)return 0;
                if((x==a||x==b)&&y<a&&(c[i][0]!=4&&c[i][0]!=2))return 0;
                if((y==a||y==b)&&x<a&&(c[i][0]!=5&&c[i][0]!=3))return 0;
            }
            return 1;
        }
        if(fl==2)
        {
            for(int i=1,x,y;i<=m;i++)
            {
                x=c[i][1]; y=c[i][2];
                if((x==a&&y==b)||(x==b&&y==a)&&c[i][0]!=1)return 0;
                if((x==a||x==b)&&(y>a&&y<b)&&(c[i][0]!=4&&c[i][0]!=2))return 0;
                if((y==a||y==b)&&(x>a&&x<b)&&(c[i][0]!=5&&c[i][0]!=3))return 0;
            }
            return 1;
        }
        if(fl==4)
        {
            for(int i=1,x=c[i][1],y=c[i][2];i<=m;i++,x=c[i][1],y=c[i][2])
                if((x==a&&y==b)||(x==b&&y==a)&&(c[i][0]==2||c[i][0]==3))return 0;
            return 1;
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d %s %d",&c[i][1],&ch,&c[i][2]);
            if(ch[0]=='=')c[i][0]=1;
            else if(ch[0]=='<'&&ch[1]=='=')c[i][0]=4;
            else if(ch[0]=='>'&&ch[1]=='=')c[i][0]=5;
            else if(ch[0]=='<')c[i][0]=2;
            else if(ch[0]=='>')c[i][0]=3;
        }
        for(int i=1;i<2*n;i++)if(ck(i,i+1,4))f[n][i][i+1]=1;
        for(int i=n-1;i;i--)
            for(int l=1;l<=2*n;l++)
                for(int r=l+1;r<=2*n;r++)
                    if(f[i+1][l][r])
                    {
    //                    printf("i=%d l=%d r=%d
    ",i,l,r);
                        int x,y;
                        if(l>2)
                        {
                            x=l-2,y=l-1;
                            if(ck(x,y,1))f[i][x][r]+=f[i+1][l][r];
    //                                         printf("f[%d][%d][%d]=%d
    ",i,x,r,f[i][x][r]);
                        }
                        if(r+2<=2*n)
                        {
                            x=r+1,y=r+2;
                            if(ck(x,y,0))f[i][l][y]+=f[i+1][l][r];
    //                                         printf("f[%d][%d][%d]=%d
    ",i,l,y,f[i][l][y]);
                        }
                        if(l>1&&r+1<=2*n)
                        {
                            x=l-1; y=r+1;
                            if(ck(x,y,2))f[i][x][y]+=f[i+1][l][r];
    //                                         printf("f[%d][%d][%d]=%d
    ",i,x,y,f[i][x][y]);
                           }
                    }
        printf("%lld
    ",f[1][1][n<<1]);
        return 0;
    }

     于是参考了一下TJ...

    调了一小时只因把 x==b 写成 y==b ?!而且还一直没仔细看...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int n,m,c[105][3];
    ll f[80][80];
    char ch[5];
    bool ck0(int a,int b)
    {
        for(int i=1,x=c[i][1],y=c[i][2];i<=m;i++,x=c[i][1],y=c[i][2])
            if(((x==a&&y==b)||(x==b&&y==a))&&(c[i][0]==2||c[i][0]==3))return 0;
        return 1;
    }
    bool ck(int l,int r,int a,int b)
    {
        for(int i=1;i<=m;i++)
        {
            int x=c[i][1],y=c[i][2],cc=c[i][0];
            bool ix=(x==a||x==b),iy=(y==a||y==b);
            bool kx=(x>=l&&x<=r),ky=(y>=l&&y<=r);
            if(cc==1&&((ix!=iy)||(kx!=ky)))return 0;//=
            if(cc==2&&(!ky&&(ix||kx)))return 0;//<
            if(cc==3&&(!kx&&(iy||ky)))return 0;//>
            if(cc==4&&((ix&&!iy&&!ky)||(kx&&!ky)))return 0;//<=
            if(cc==5&&((iy&&!ix&&!kx)||(ky&&!kx)))return 0;//>=
        }
        return 1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        bool flag=0; int cnt=0;
        for(int i=1,x,y,cc;i<=m;i++)
        {
            scanf("%d %s %d",&x,&ch,&y);
            if(ch[0]=='=')cc=1;
            else if(ch[0]=='<'&&ch[1]=='=')cc=4;
            else if(ch[0]=='>'&&ch[1]=='=')cc=5;
            else if(ch[0]=='<')cc=2;
            else if(ch[0]=='>')cc=3;
            if(x==y)
            {
                if(cc==2||cc==3)flag=1;
                continue;//!
            }
            c[++cnt][1]=x; c[cnt][2]=y; c[cnt][0]=cc;
        }
        if(flag){printf("0
    "); return 0;}
        m=cnt;
        for(int i=1;i<2*n;i++)if(ck0(i,i+1))f[i][i+1]=1;
        for(int l=4;l<=2*n;l+=2)
            for(int i=1;i<=2*n-l+1;i++)
            {
                int j=i+l-1;
                if(ck(i+2,j,i,i+1))f[i][j]+=f[i+2][j];
                if(ck(i,j-2,j-1,j))f[i][j]+=f[i][j-2];
                if(ck(i+1,j-1,i,j))f[i][j]+=f[i+1][j-1];
            }
        printf("%lld
    ",f[1][2*n]);
        return 0;
    }
  • 相关阅读:
    [CF1398E] Two Types of Spells
    [CF1399E2] Weights Division (hard version)
    [CF1400E] Clear the Multiset
    Review 2020.10.29
    Review 2020.10.11
    [CF1409F] Subsequences of Length Two
    [CF1413E] Solo mid Oracle
    [2020CCPC威海C] Rencontre
    [2020CCPC威海B] Labyrinth
    phpredis实现简单的消息队列
  • 原文地址:https://www.cnblogs.com/Zinn/p/9672540.html
Copyright © 2011-2022 走看看