bzoj4325: NOIP2015 斗地主

题目

题解:

题解

#include
using namespace std;
#define X f[i][j][k][l]
inline void M(int &x,int y){
    if (x>y) x=y;
}
int p[15],f[25][25][25][25],x,y,K,h[5],T,n,i,ans,shun[4]={0,5,3,2},j,k,l;
int calc(int O,int t,int T,int F,int K){
//O表示one,t表示two,T表示three,F表示four,K表示king,王的个数
    if (K==1) K=0,O++;
    if (!K) return f[F][T][t][O];
    return min(f[F][T][t][O]+1,f[F][T][t][O+2]);
}
void dfs(int now){
    if (now>ans) return;
    memset(h,0,sizeof(h));
    for (int i=2;i<=14;i++) h[p[i]]++;
    M(ans,now+calc(h[1],h[2],h[3],h[4],K));
    for (int k=1;k<=3;k++)
        for (int i=3,j;i<=14;i++){
            for (j=i;j<=14 && p[j]>=k;j++){
                p[j]-=k;
                if (j-i+1>=shun[k]) dfs(now+1);
            }
            for (j--;j>=i;j--) p[j]+=k;
        }
}
int main(){
    scanf("%d%d",&T,&n);
    for (i=0;i<=n/4;i++)
        for (j=0;j<=n/3;j++)
            for (k=0;k<=n/2;k++)
                for (l=0;i*4+j*3+k*2+l<=n;l++){
                 //i个4,j个3,k个2,l个1
                    X=i+j+k+l;
                    if (i){
                        M(X,f[i-1][j+1][k][l+1]);//四拆成三和一个单
                        if (k>1) M(X,f[i-1][j][k-2][l]+1);//四带两对
                        if (i>1) M(X,f[i-2][j][k][l]+1);//两炸拆成四带两对
                        if (k) M(X,f[i-1][j][k-1][l]+1);//四带两张成对的单
                        if (l>1) M(X,f[i-1][j][k][l-2]+1);//四带二
                        M(X,f[i-1][j][k][l]+1);//直接炸
                    }
                    if (j){
                        M(X,f[i][j-1][k+1][l+1]);//三拆成一对一单
                        if (k) M(X,f[i][j-1][k-1][l]+1);//三带一对
                        if (l) M(X,f[i][j-1][k][l-1]+1);//三带一
                        M(X,f[i][j-1][k][l]+1);//直接三个
                    }
                    if (k) M(X,f[i][j][k-1][l]+1);//直接出对子
                    if (l) M(X,f[i][j][k][l-1]+1);//直接出单
                }
    while (T--){
        memset(p,0,sizeof(p));K=0;
        for (i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            if (!x) K++;
            else if (x==1) p[14]++;
            else p[x]++;
        }
        ans=n;
        dfs(0);
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(搜索,dp)