麻雀+ DP]羅区P5301

トピックまあについて書くつもりミルクCSPテスト麻雀麻雀の一口......

我々は単純なポイント= =を選んだので、しかし、それはCSPであるため、

まず邦夫は、直接、比類のない(13 ^ 2 \)\列挙、7組は貪欲することができ

それ以来(2 4 ^ * \。4 Binom {} {}。4 <2。3 ^ * \。4 Binom {} {}。3 \)\、そう厚いスティックは、役に立たないので、彼だけ列挙\(3 \ times4 2 \)の場合

セット\(DP [POS] [J ] [0/1] [I1] [I2] \) 最初に今列挙表す\(POS \)と、カードの種類\(J \)を伴うまたは鳥無し面、ヘッドがある(I1 \)は\ \(POS-1、POS、 POS + 1 \)を用いて、直線状である\(I2 \) A \(POS、POS + 1、 POS + 2 \) ストレートのは状況

次に、あなたが見つけたときに(I1 \ GEQ 3 \)\、組成物は、直接することができ(\ 3)\、ポン\(I2 \)同様に

だから、(I1、I2 \)\にのみ列挙(2 \)\

各転送ライセンス暴力カテゴリー話は、クロスボーダーの配列に注意を払うことはありません

非常に短いコードを感じます

#include <bits/stdc++.h>
#define N
#define ll long long
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
//1-9:万 10-18:索 19-27:筒 28-32:东西南北中 33:白 34:发 
ll dp[40][5][2][3][3],ans=0,qd[40],_2[40],C[40][40];//pos,面子,雀头,pos-1 pos pos+1,pos pos+1 pos+2 
char s[5];
int num[40],gsws[14]={0,1,9,10,18,19,27,28,29,30,31,32,33,34};
bool is[40];
void init(){
    For(i,1,34) num[i]=4,is[i]=0;
    For(i,0,34) For(j,0,4) For(k,0,1) For(p,0,2) For(q,0,2)
        dp[i][j][k][p][q]=0;
}
void getcard(){
    while(1){
        scanf("\n%s",s+1);
        int l=strlen(s+1);
        if(s[1]=='0') break;
        if(l==2){
            if(s[2]=='m') num[s[1]-'0']--;
            else if(s[2]=='s') num[s[1]-'0'+9]--;
            else if(s[2]=='p') num[s[1]-'0'+18]--;          
        } else{
            if(s[1]=='E') num[28]--;
            else if(s[1]=='W') num[29]--;
            else if(s[1]=='S') num[30]--;
            else if(s[1]=='N') num[31]--;
            else if(s[1]=='Z') num[32]--;
            else if(s[1]=='B') num[33]--;
            else if(s[1]=='F') num[34]--;
        }
    }
    while(1){
        scanf("\n%s",s+1);
        if(s[1]=='0') break;
        int l=strlen(s+1);
        if(l==2){
            if(s[2]=='m') is[s[1]-'0']=1;
            else if(s[2]=='s') is[s[1]-'0'+9]=1;
            else if(s[2]=='p') is[s[1]-'0'+18]=1;
        } else{
            if(s[1]=='E') is[28]=1;
            else if(s[1]=='W') is[29]=1;
            else if(s[1]=='S') is[30]=1;
            else if(s[1]=='N') is[31]=1;
            else if(s[1]=='Z') is[32]=1;
            else if(s[1]=='B') is[33]=1;
            else if(s[1]=='F') is[34]=1;
        }
    }   
}
void upd(ll &x,ll y){ x<y?x=y:x=x; }
ll calc(int x,int y){ return (is[x]?_2[y]:1)*C[num[x]][y]; }

ll GSWS(){
    ll qwq=0;
    For(i,1,13) if(!num[gsws[i]]) return 0;
    For(i,1,13){
        ll tmp=1;
        if(num[gsws[i]]>=2){
            For(j,1,13){
                if(i==j) tmp*=calc(gsws[j],2);
                else tmp*=calc(gsws[j],1);
            } 
        }
        qwq=max(qwq,tmp);
    }
    return qwq*13ll;
}

ll QD(){
    ll qwq=1;int ewe=0;
    For(i,1,34) if(num[i]>=2) qd[++ewe]=calc(i,2);
    if(ewe<7) return 0;
    sort(qd+1,qd+ewe+1);
    Rof(i,ewe,ewe-6) qwq*=qd[i];
    return qwq*7ll;
}

void solve(){
    init(),ans=0;
    getcard();
    ans=max(ans,GSWS());
    ans=max(ans,QD());
    
    dp[0][0][0][0][0]=1;
    For(pos,0,33) For(j,0,4) For(qt,0,1) For(i1,0,2) For(i2,0,2){
        if(!dp[pos][j][qt][i1][i2]) continue;
        int lim=0;
        if(pos+1<=27 && pos+3<=(pos/9+1)*9) lim=2;
        if(!qt){
            if(num[pos+1]-i1-i2>=2){
                For(k,0,(num[pos+1]-i1-i2-2)/3) For(i3,0,lim){
                    if(i2+i3>num[pos+2] || i1+i2+i3+k*3+2>num[pos+1] || i3>num[pos+3] || j+i3+k>4) continue;
                    int tmp=i1+i2+i3+k*3+2;
                    upd(dp[pos+1][j+i3+k][1][i2][i3],dp[pos][j][qt][i1][i2]*calc(pos+1,tmp));
                }                   
            }
        }
        For(k,0,(num[pos+1]-i1-i2)/3) For(i3,0,lim){
            if(i2+i3>num[pos+2] || i1+i2+i3+3*k>num[pos+1] || i3>num[pos+3] || j+i3+k>4) continue;
            int tmp=i1+i2+i3+k*3;
            upd(dp[pos+1][j+i3+k][qt][i2][i3],dp[pos][j][qt][i1][i2]*calc(pos+1,tmp));
        }
    }
    
    ans=max(ans,dp[34][4][1][0][0]);
    printf("%lld\n",ans);
}

int main(){
    C[0][0]=_2[0]=1;
    For(i,1,34) C[i][0]=1;
    For(i,1,34) For(j,1,i) C[i][j]=C[i-1][j]+C[i-1][j-1];
    For(i,1,34) _2[i]=2ll*_2[i-1];
    int T;scanf("%d",&T);
    while(T--) solve();
}

おすすめ

転載: www.cnblogs.com/PsychicBoom/p/11861035.html