zoukankan      html  css  js  c++  java
  • luogu P5301 [GXOI/GZOI2019]宝牌一大堆

    传送门

    wdnm又是打麻将

    首先国土无双可以直接枚举哪种牌用了(2)次算贡献,然后(7)个对子可以把每种牌的对子贡献排序,取最大的(7)个,剩下的牌直接暴力枚举是不行的,考虑dp,设(f_{i,0sim1,j,k,0sim4,0sim4}),表示考虑前(i)种牌,(0sim1)个对子,(j)(i-1,i,i+1)顺子,(k)(i,i+1,i+2)顺子,(0sim4)个面子,(0sim4)个杠子,的最大价值,转移枚举下一种牌(i)怎么放,可以放杠子,或者放(i,i+1,i+2)的顺子同时考虑放对子和刻子,然后最后用对应牌型的dp值更新答案

    注意顺子的限制条件,同时建议限制一下状态中牌的总数不超过(18)

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=40;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    map<string,int> id;
    char cc[3];
    void inii()
    {
        id["B"]=0;
        id["1m"]=1;
        id["2m"]=2;
        id["3m"]=3;
        id["4m"]=4;
        id["5m"]=5;
        id["6m"]=6;
        id["7m"]=7;
        id["8m"]=8;
        id["9m"]=9;
        id["1p"]=10;
        id["2p"]=11;
        id["3p"]=12;
        id["4p"]=13;
        id["5p"]=14;
        id["6p"]=15;
        id["7p"]=16;
        id["8p"]=17;
        id["9p"]=18;
        id["1s"]=19;
        id["2s"]=20;
        id["3s"]=21;
        id["4s"]=22;
        id["5s"]=23;
        id["6s"]=24;
        id["7s"]=25;
        id["8s"]=26;
        id["9s"]=27;
        id["E"]=28;
        id["S"]=29;
        id["W"]=30;
        id["N"]=31;
        id["Z"]=32;
        id["F"]=33;
    }
    int c[5][5]={{1},{1,1},{1,2,1},{1,3,3,1},{1,4,6,4,1}},cn[N];
    bool qb[N];
    int gtws[13]={1,9,10,18,19,27,28,29,30,31,32,0,33};
    LL f[2][2][3][3][5][5],qdz[N],ans;
    
    int main()
    {
        inii();
        int T=rd();
        while(T--)
        {
            ans=0;
            for(int i=0;i<34;++i) cn[i]=4,qb[i]=0;
            while(1)
            {
                scanf("%s",cc);
                if(cc[0]=='0') break;
                --cn[id[cc]];
            }
            while(1)
            {
                scanf("%s",cc);
                if(cc[0]=='0') break;
                qb[id[cc]]=1;
            }
            bool fg=1;
            for(int i=0;fg&&i<13;++i) fg=cn[gtws[i]];
            if(fg)
            {
                LL sm=13;
                for(int i=0;i<13;++i) sm*=(1ll<<qb[gtws[i]])*cn[gtws[i]];
                for(int i=0;i<13;++i)
                    if(cn[gtws[i]]>=2) ans=max(ans,sm*(1ll<<qb[gtws[i]])*(cn[gtws[i]]-1)/2);
            }
            int m=0;
            for(int i=0;i<34;++i)
                if(cn[i]>=2) qdz[++m]=(1ll<<(qb[i]*2))*c[cn[i]][2];
            if(m>=7)
            {
                sort(qdz+1,qdz+m+1);
                LL sm=7;
                for(int i=1;i<=7;++i) sm*=qdz[m-i+1];
                ans=max(ans,sm);
            }
            memset(f,0,sizeof(f));
            int nw=1,la=0;
            f[la][0][0][0][0][0]=1;
            for(int i=0;i<34;++i)
            {
                for(int j=0;j<=1;++j)
                    for(int k=0;k<=2;++k)
                        for(int l=0;l<=2;++l)
                            for(int p=0;p<=4&&j*2+p*3<=18;++p)
                                for(int q=0;q<=4&&j*2+p*3+q*4<=18;++q)
                                {
                                    if(!f[la][j][k][l][p][q]) continue;
                                    int res=cn[i]-k-l,lm=min(i>=1&&i<=27&&(i-1)%9+1<=7?2:0,res);
                                    for(int o=0;o<=lm&&o<=cn[i+1]-l&&o<=cn[i+2]&&p+o<=4&&j*2+(p+o)*3+q*4<=18;++o)
                                    {
                                        LL dt=1ll<<(o*(qb[i]+qb[i+1]+qb[i+2]));
                                        f[nw][j][l][o][p+o][q]=max(f[nw][j][l][o][p+o][q],f[la][j][k][l][p][q]*dt*c[cn[i]][o+k+l]);
                                        if(o+2<=res&&!j&&(j+1)*2+(p+o)*3+q*4<=18) f[nw][j+1][l][o][p+o][q]=max(f[nw][j+1][l][o][p+o][q],f[la][j][k][l][p][q]*dt*c[cn[i]][o+k+l+2]*(1<<(qb[i]*2)));
                                        if(o+3<=res&&p+o+1<=4&&j*2+(p+o+1)*3+q*4<=18) f[nw][j][l][o][p+o+1][q]=max(f[nw][j][l][o][p+o+1][q],f[la][j][k][l][p][q]*dt*c[cn[i]][o+k+l+3]*(1<<(qb[i]*3)));
                                    }
                                    if(res==4&&q+1<=4&&j*2+p*3+(q+1)*4<=18) f[nw][j][l][0][p][q+1]=max(f[nw][j][l][0][p][q+1],f[la][j][k][l][p][q]*c[cn[i]][4]*(1<<(qb[i]*4)));
                                    f[la][j][k][l][p][q]=0;
                                }
                nw^=1,la^=1;
            }
            ans=max(ans,f[la][1][0][0][4][0]);
            ans=max(ans,f[la][1][0][0][3][1]);
            ans=max(ans,f[la][1][0][0][2][2]);
            ans=max(ans,f[la][1][0][0][1][3]);
            ans=max(ans,f[la][1][0][0][0][4]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Java内存模型(JMM)是什么?JMM 通过控制主内存与每个线程的本地内存之间的交互,来提供内存可见性保证
    【普及组_在线赛】班级聚会(reuntion)
    面试官:你对Redis缓存了解吗?面对这11道面试题是否有很多问号?
    【华为云技术分享】浅谈产品模型(Profile)在程序设计中的作用
    【华为云技术分享】LiteAI四大绝招,解锁物联网智能设备AI开发难关
    【华为云技术分享】漫谈Huawei LiteOS五大内核模块
    科技感满满,华为云DevCloud推出网页暗黑模式
    赶在520之前,程序员如何用Python送上最特别的“我爱你”表白
    【华为云技术分享】从部署和运维说说DLI(1)
    【2017.11.25普及组模拟】The Farthest House题解
  • 原文地址:https://www.cnblogs.com/smyjr/p/10763030.html
Copyright © 2011-2022 走看看