Luogu2540 斗地主增强版(搜索+动态规划)

  单纯的暴搜似乎还是很好写的,然而过不了。出完顺子之后答案是可以dp出来的,于是大力搜然后大力dp就好了。

  dp时强行讨论完了几乎所有拆牌情况,理性愉悦一发。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int T,n,cnt[20],f[24][13][9][7][3],ans;//1:2 2~12:3~K 13:A 14 15:ghost
void dfs(int k,int step);
void threestraight(int k,int step)
{
    for (int i=2;i<=12;i++)
    if (cnt[i]>=3&&cnt[i+1]>=3)
    {
        cnt[i]-=3,cnt[i+1]-=3;dfs(k-6,step+1);
        int t=i+1;while (cnt[t+1]>=3) t++,cnt[t]-=3,dfs(k-(t-i+1)*3,step+1);
        while (t>=i) cnt[t]+=3,t--;
    }
}
void twostraight(int k,int step)
{
    for (int i=2;i<=11;i++)
    if (cnt[i]>=2&&cnt[i+1]>=2&&cnt[i+2]>=2)
    {
        cnt[i]-=2,cnt[i+1]-=2,cnt[i+2]-=2;dfs(k-6,step+1);
        int t=i+2;while (cnt[t+1]>=2) t++,cnt[t]-=2,dfs(k-((t-i+1)<<1),step+1);
        while (t>=i) cnt[t]+=2,t--; 
    }
}
void onestraight(int k,int step)
{
    for (int i=2;i<=9;i++)
    if (cnt[i]&&cnt[i+1]&&cnt[i+2]&&cnt[i+3]&&cnt[i+4]) 
    {
        cnt[i]--,cnt[i+1]--,cnt[i+2]--,cnt[i+3]--,cnt[i+4]--;dfs(k-5,step+1);
        int t=i+4;while (t<13&&cnt[t+1]) t++,cnt[t]--,dfs(k-(t-i+1),step+1);
        while (t>=i) cnt[t]++,t--;
    }
}
void dfs(int k,int step)
{
    int t[6]={0};
    for (int i=1;i<=13;i++) if (cnt[i]) t[cnt[i]]++;
    t[5]=cnt[14]+cnt[15];
    ans=min(ans,step+f[t[1]][t[2]][t[3]][t[4]][t[5]]);
    if (step+(k>0)>=ans) return;
    if (k==0) return;
    threestraight(k,step);
    twostraight(k,step);
    onestraight(k,step);
}
inline void update(int &x,int y){x=min(x,y);}
void dp()
{
    memset(f,42,sizeof(f));
    f[0][0][0][0][0]=0;
    for (int i=1;i<=n;i++)
        for (int x=0;x<=i;x++)
            for (int y=0;y*2<=i-x;y++)
                for (int z=0;z*3<=i-x-y*2;z++)
                    for (int t=0;t*4<=i-x-y*2-z*3;t++)
                        for (int g=0;g<=min(2,i-x-y*2-z*3-t*4);g++)
                        {
                            if (x) update(f[x][y][z][t][g],f[x-1][y][z][t][g]+1);
                            if (y) update(f[x][y][z][t][g],f[x][y-1][z][t][g]+1);
                            if (y) update(f[x][y][z][t][g],f[x+1][y-1][z][t][g]+1);
                            if (z) update(f[x][y][z][t][g],f[x][y][z-1][t][g]+1);
                            if (z) update(f[x][y][z][t][g],f[x][y+1][z-1][t][g]+1);
                            if (z) update(f[x][y][z][t][g],f[x+1][y][z-1][t][g]+1);
                            if (t) update(f[x][y][z][t][g],f[x][y][z][t-1][g]+1);
                            if (t) update(f[x][y][z][t][g],f[x][y][z+1][t-1][g]+1);
                            if (t) update(f[x][y][z][t][g],f[x][y+1][z][t-1][g]+1);
                            if (t) update(f[x][y][z][t][g],f[x+1][y][z][t-1][g]+1);
                            if (g) update(f[x][y][z][t][g],f[x][y][z][t][g-1]+1);
                            if (g==2) update(f[x][y][z][t][g],f[x][y][z][t][g-2]+1);
                            //part 1 only one
                            if (z&&x) update(f[x][y][z][t][g],f[x-1][y][z-1][t][g]+1);
                            if (z&&y) update(f[x][y][z][t][g],f[x+1][y-1][z-1][t][g]+1);
                            if (z>=2) update(f[x][y][z][t][g],f[x][y+1][z-2][t][g]+1);
                            if (z&&g) update(f[x][y][z][t][g],f[x][y][z-1][t][g-1]+1);
                            if (t&&y) update(f[x][y][z][t][g],f[x+2][y-1][z][t-1][g]+1);
                            if (t>=2) update(f[x][y][z][t][g],f[x+1][y][z+1][t-2][g]+1);
                            if (t&&g) update(f[x][y][z][t][g],f[x][y][z][t-1][g-1]+1);
                            //part 2 three with one
                            if (z&&y) update(f[x][y][z][t][g],f[x][y-1][z-1][t][g]+1);
                            if (z>=2) update(f[x][y][z][t][g],f[x+1][y][z-2][t][g]+1);
                            if (z&&t) update(f[x][y][z][t][g],f[x][y+1][z-1][t-1][g]+1);
                            if (t&&y) update(f[x][y][z][t][g],f[x+1][y-1][z][t-1][g]+1);
                            if (t&&z) update(f[x][y][z][t][g],f[x+2][t][z-1][t-1][g]+1);
                            if (t>=2) update(f[x][t][z][t][g],f[x+1][y+1][z][t-2][g]+1);
                            //part 3 three with two
                            if (t)
                            {
                                if (x>=2) update(f[x][y][z][t][g],f[x-2][y][z][t-1][g]+1);
                                if (x&&g) update(f[x][y][z][t][g],f[x-1][y][z][t-1][g-1]+1);
                                if (y) update(f[x][y][z][t][g],f[x][y-1][z][t-1][g]+1);
                                if (y>=2) update(f[x][y][z][t][g],f[x+2][y-2][z][t-1][g]+1);
                                if (y&&g) update(f[x][y][z][t][g],f[x+1][y-1][z][t-1][g-1]+1);
                                if (z) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1);
                                if (z&&x) update(f[x][y][z][t][g],f[x-1][y+1][z-1][t-1][g]+1);
                                if (z&&y) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1);
                                if (z>=2) update(f[x][y][z][t][g],f[x][y+1][z-2][t-1][g]+1);
                                if (z&&g) update(f[x][y][z][t][g],f[x][y+1][z-1][t-1][g-1]+1);
                                if (t>=2) update(f[x][y][z][t][g],f[x][y+1][z][t-2][g]+1);
                                if (t>=3) update(f[x][y][z][t][g],f[x][y][z+2][t-3][g]+1);
                                if (t>=2&&x) update(f[x][y][z][t][g],f[x-1][y][z+1][t-2][g]+1);
                                if (t>=2&&y) update(f[x][y][z][t][g],f[x+1][y-1][z+1][t-2][g]+1);
                                if (t>=2&&z) update(f[x][y][z][t][g],f[x][y+1][z][t-2][g]+1);
                                if (t>=2&&g) update(f[x][y][z][t][g],f[x][y][z+1][t-2][g-1]+1);
                                if (g>=2) update(f[x][y][z][t][g],f[x][y][z][t-1][g-2]+1);
                                //part 4 four with one
                                if (y>=2) update(f[x][y][z][t][g],f[x][y-2][z][t-1][g]+1);
                                if (z>=2) update(f[x][y][z][t][g],f[x+2][y][z-2][t-1][g]+1);
                                if (y&&z) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1);
                                if (t>=2&&z) update(f[x][y][z][t][g],f[x+1][y+1][z-1][t-2][g]+1);
                                if (t>=2) update(f[x][y][z][t][g],f[x][y][z][t-2][g]+1);
                                if (t>=3) update(f[x][y][z][t][g],f[x][y+2][z][t-3][g]+1);
                                //part 5 four with two
                            }
                        }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("2540.in","r",stdin);
    freopen("2540.out","w",stdout);
    const char LL[]="%I64d
";
#else
    const char LL[]="%lld
";
#endif
    T=read(),n=read();
    dp();
    while (T--)
    {
        ans=n;memset(cnt,0,sizeof(cnt));
        for (int i=1;i<=n;i++)
        {
            int x=read(),y=read();
            if (x==0) cnt[y+13]++;
            else if (x==2) cnt[1]++;
            else if (x==1) cnt[13]++;
            else cnt[x-1]++;
        }
        dfs(n,0);
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Gloid/p/9786635.html