luogu P5301 [GXOI/GZOI2019]宝牌一大堆

传送门

wdnm又是打麻将

首先国土无双可以直接枚举哪种牌用了\(2\)次算贡献,然后\(7\)个对子可以把每种牌的对子贡献排序,取最大的\(7\)个,剩下的牌直接暴力枚举是不行的,考虑dp,设\(f_{i,0\sim1,j,k,0\sim4,0\sim4}\),表示考虑前\(i\)种牌,\(0\sim1\)个对子,\(j\)\(i-1,i,i+1\)顺子,\(k\)\(i,i+1,i+2\)顺子,\(0\sim4\)个面子,\(0\sim4\)个杠子,的最大价值,转移枚举下一种牌\(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\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/smyjr/p/10763030.html