• 洛谷P2593 [ ZJOI 2006 ] 超级麻将 —— DP


    题目:https://www.luogu.org/problemnew/show/P2593

    DP的话,考虑到当前这一位只跟前两位有关,所以记录一下这3位的状态就行;

    于是一开始记录的第 i 位,i-1 位的数量,i-2 位的数量,是否有过对子,然后可行性DP;

    但是写得太丑,又WA又T...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,a[105];
    bool f[105][105][105][3];
    int rd()
    {
        int ret=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
        return ret*f;
    }
    int main()
    {
        scanf("%d",&n);
        while(n--)
        {
            memset(a,0,sizeof a);
            memset(f,0,sizeof f);
            for(int i=1;i<=100;i++)a[i]=rd();
            f[0][0][0][0]=1;
            for(int i=1;i<=100;i++)
                for(int j=0;j<=(i-2>0?a[i-2]:0);j++)
                    for(int k=j;k<=(i-1>0?a[i-1]:0);k++)    if(f[i-1][j][k][0]||f[i-1][j][k][1])
                    {
                        if(a[i]>=j)f[i][k-j][a[i]-j][0]=f[i-1][j][k][0];
                        if(a[i]>=j)f[i][k-j][a[i]-j][1]=f[i-1][j][k][1];
                        if(a[i]-j>=2&&f[i-1][j][k][0])f[i][k-j][a[i]-j-2][1]=1; 
                        for(int l=1;a[i]-j>=3*l;l++)
                        {
                            if(a[i]-j>=3*l)
                            {
                                f[i][k-j][a[i]-j-3*l][0]=f[i-1][j][k][0];
                                f[i][k-j][a[i]-j-3*l][1]=f[i-1][j][k][1];
                            }
                            if(a[i]-j>=4*l)
                            {
                                f[i][k-j][a[i]-j-4*l][0]=f[i-1][j][k][0];
                                f[i][k-j][a[i]-j-4*l][1]=f[i-1][j][k][1];
                            }
                        }
                    }
            if(f[100][0][0][1])printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }

    于是放弃这个写法了...

    看到TJ,记录的是第 i 位和第 i-1 位的数量,这样就可以同层转移啦!于是简洁好多;

    但总感觉复杂度有点不对啊,这样最高不是 10^8 吗...总之加上 register 就卡过去了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,a[105];
    bool f[105][105][105][3];
    int rd()
    {
        int ret=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
        return ret*f;
    }
    int main()
    {
        n=rd();
        while(n--)
        {
            memset(f,0,sizeof f);
            for(register int i=1;i<=100;i++)a[i]=rd();
            f[0][0][0][0]=1;
            for(register int i=1;i<=100;i++)
                for(register int j=0;j<=(i-1>0?a[i-1]:0);j++)
                    for(register int k=0;k<=a[i];k++)
                    {
                        if(k>=2)f[i][j][k][1]|=f[i][j][k-2][0];//可以同层转移囧 
                        if(k>=3)f[i][j][k][0]|=f[i][j][k-3][0],f[i][j][k][1]|=f[i][j][k-3][1];
                        if(k>=4)f[i][j][k][0]|=f[i][j][k-4][0],f[i][j][k][1]|=f[i][j][k-4][1];
                        if(k<=j&&k<=a[i-2])f[i][j][k][0]|=f[i-1][a[i-2]-k][j-k][0],
                                           f[i][j][k][1]|=f[i-1][a[i-2]-k][j-k][1];
                    }
            if(f[100][a[99]][a[100]][1])printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    jquery Flexigrid只选择一行,增加双击事件,获取数据库ID
    [工具库]JOJSONBuilder工具类——一键把多个bean对象数据转换为JSON格式数据
    java 观察者模式
    [工具库]JOXMLBuilder工具类——一键把多个bean对象数据转换为XML格式数据
    JVM原理
    WEB项目的分层结构
    一刻钟精通正则表达式
    [Java]Stack栈和Heap堆的区别(终结篇)[转]
    [java]二、八、十、十六进制之间的转换
    java 适配器模式
  • 原文地址:https://www.cnblogs.com/Zinn/p/9369899.html
Copyright © 2020-2023  润新知