【BZOJ5503】[GXOI/GZOI2019]寶牌一大堆(動態規劃)

【BZOJ5503】[GXOI/GZOI2019]寶牌一大堆(動態規劃)

題面

BZOJ
洛谷php

題解

首先特殊牌型直接特判。
而後剩下的部分能夠直接\(dp\),直接把全部能夠存的所有帶進去大力\(dp\)就好了。
發現每多一張牌胡的本質就是把一個刻字換成槓子,因此這兩個東西記錄在一塊兒就好了。
那麼狀態就是\(f[i][0/1/2/3/4][0/1/2][0/1/2][0/1]\)
分別表示刻字、槓子、順子的數量,\(i-1,i,i+1\)的順子數量,\(i,i+1,i+2\)的順子的數量,以及是否已經有對子。
轉移比較容易。ios

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 140
int Read()
{
    char ch[3];scanf("%s",ch);
    if(ch[0]=='E')return 28;if(ch[0]=='S')return 29;
    if(ch[0]=='W')return 30;if(ch[0]=='N')return 31;
    if(ch[0]=='Z')return 32;if(ch[0]=='B')return 33;
    if(ch[0]=='F')return 34;if(ch[0]=='0')return 0;
    int x=ch[0]-48;if(ch[1]=='p')x+=9;if(ch[1]=='s')x+=18;
    return x;
}
ll C[MAX][MAX];
int n,s[MAX];bool book[MAX];
ll f[35][6][3][3][2];
int pre[14]={0,1,9,10,18,19,27,28,29,30,31,32,33,34};
int bin[10]={1,2,4,8,16,32,64,128,256,512};
void cmax(ll &x,ll y){x=max(x,y);}
int main()
{
    for(int i=0;i<10;++i)C[i][0]=1;
    for(int i=1;i<10;++i)
        for(int j=1;j<=i;++j)C[i][j]=C[i-1][j]+C[i-1][j-1];
    int T,x;scanf("%d",&T);
    while(T--)
    {
        for(int i=1;i<=34;++i)s[i]=4,book[i]=false;
        while((x=Read()))s[x]-=1;
        while((x=Read()))book[x]=true;
        ll ans=0;
        //Task1
        {
            bool fl=true;int mx=0;ll ret=1;
            for(int i=1;i<=13;++i)
                if(!s[pre[i]]){fl=false;break;}
                else mx=max(mx,(s[pre[i]]-1)*(book[pre[i]]?2:1)),ret=ret*(book[pre[i]]?2:1)*s[pre[i]];
            if(fl)ret=ret*mx*13/2,ans=max(ans,ret);
        }
        //Task2
        {
            vector<int> val;
            for(int i=1;i<=34;++i)
                if(s[i]>=2)val.push_back((book[i]?4:1)*(s[i]*(s[i]-1)/2));
            sort(val.begin(),val.end());
            if(val.size()>=7)
            {
                ll ret=1;
                for(int i=7;i;--i)ret*=val.back(),val.pop_back();
                ans=max(ans,ret*7);
            }
        }
        //Task3
        {
            memset(f,0,sizeof(f));
            f[0][0][0][0][0]=1;
            for(int i=1;i<=34;++i)
                for(int j=0;j<5;++j)
                    for(int k=0;k<3&&j+k<=4&&k<=s[i];++k)
                    {
                        if(k>0&&(i==10||i==19||i>=28||i==11||i==20))break;
                        for(int l=0;l<3&&j+k+l<=4&&k+l<=s[i];++l)
                        {
                            if(l>0&&(l==9||i==18||i==27||i==10||i==19||i>=28))break;
                            if(!f[i-1][j][k][l][0]&&!f[i-1][j][k][l][1])continue;
                            for(int m=0;k+l+m<=s[i]&&m<3;++m)
                            {
                                if(m>0&&(i==9||i==18||i>=27))continue;
                                if(s[i]>=4+k+l+m)
                                {
                                    cmax(f[i][j+1+k][l][m][0],(book[i]?16:1)*f[i-1][j][k][l][0]);
                                    cmax(f[i][j+1+k][l][m][1],(book[i]?16:1)*f[i-1][j][k][l][1]);
                                }
                                if(s[i]>=3+k+l+m)
                                {
                                    cmax(f[i][j+1+k][l][m][0],(book[i]?bin[3+k+l+m]:1)*C[s[i]][3+k+l+m]*f[i-1][j][k][l][0]);
                                    cmax(f[i][j+1+k][l][m][1],(book[i]?bin[3+k+l+m]:1)*C[s[i]][3+k+l+m]*f[i-1][j][k][l][1]);
                                }
                                if(s[i]>=2+k+l+m)
                                {
                                    cmax(f[i][j+k][l][m][1],(book[i]?bin[2+k+l+m]:1)*C[s[i]][2+k+l+m]*f[i-1][j][k][l][0]);
                                }
                                if(s[i]>=k+l+m)
                                {
                                    cmax(f[i][j+k][l][m][0],(book[i]?bin[k+l+m]:1)*C[s[i]][k+l+m]*f[i-1][j][k][l][0]);
                                    cmax(f[i][j+k][l][m][1],(book[i]?bin[k+l+m]:1)*C[s[i]][k+l+m]*f[i-1][j][k][l][1]);
                                }
                            }
                        }
                    }
            ans=max(ans,f[34][4][0][0][1]);
        }
        printf("%lld\n",ans);
    }
}
相關文章
相關標籤/搜索