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;
    }
    
  • 相关阅读:
    进度条
    html5 表单新增事件
    html5 表单的新增type属性
    html5 表单的新增元素
    html5 语义化标签
    jq 手风琴案例
    codeforces 702D D. Road to Post Office(数学)
    codeforces 702C C. Cellular Network(水题)
    codeforces 702B B. Powers of Two(水题)
    codeforces 702A A. Maximum Increase(水题)
  • 原文地址:https://www.cnblogs.com/smyjr/p/10763030.html
Copyright © 2011-2022 走看看