vijos p1980斗地主/luogu p2540斗地主增强版

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vijos p1980斗地主/luogu p2540斗地主增强版相关的知识,希望对你有一定的参考价值。

https://vijos.org/p/1980

https://www.luogu.org/problemnew/show/2540

这两题的数据比原版斗地主数据要毒瘤多了......特别是vj的一百个点......

把我在vj上写的题解发一下吧......

 

dp[i][j][k][l][m]表示不考虑顺子的情况下,(数码相同的牌有四张的有i种【emmm也就是不算王炸的纯炸弹有x个】,以此类推,有三张的有j种,两张的有k种,一张的有l种,特别的,王的数量为m个)的情况,最少能够出完牌的次数。
王之所以分开考虑是因为王炸不能算对子,四带两对和三带一对的情况对于王炸要分开考虑,与其特判不如直接新开一维记录
先预处理出能够用得到的dp数组的值,然后dfs枚举顺子
本来dp数组中没有考虑拆牌的情况,只有十多行的状态转移,洛谷上面的原版斗地主能够a掉,但是洛谷的斗地主加强版和vijos的斗地主都不行
于是狠心把所有能够考虑到的拆牌的情况都写了进去,令人窒息的五十行if......
其实有的拆牌情况可以不用考虑的,只是我当时实在是不想思考了......
幸好一遍过,没有怎么调试,否则我会疯的......

 

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#define MAX4 7
#define MAX3 9
#define MAX2 14
#define MAX1 25
#define MAX0 2
using namespace std;
int T,n;
int card[30];
int dp[8][10][15][26][3];
int finalans;
inline int read()
{
    int k=0,f=1;char c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){k=k*10+c-‘0‘;c=getchar();}
    return k*f;
}
inline void DpBuild()
{
    for(int i=0;i<=MAX4;i++)
    {
        for(int j=0;j<=MAX3;j++)
        {
            for(int k=0;k<=MAX2;k++)
            {
                for(int l=0;l<=MAX1;l++)
                {
                    for(int m=0;m<=MAX0;m++)
                    {
                        dp[i][j][k][l][m]=i+j+k+l+(m==0?0:1);
                    }
                }
            }
        }
    }
    for(int i=0;i<=MAX4;i++)
    {
        int usingj=(MAX1-4*i)/3+1;
        for(int j=0;j<=usingj;j++)
        {
            int usingk=(MAX1-4*i-3*j)/2+1;
            for(int k=0;k<=usingk;k++)
            {
                int usingl=(MAX1-4*i-3*j-2*k)+1;
                for(int l=0;l<=usingl;l++)
                {
                    for(int m=0;m<=MAX0;m++)
                    {
                        if(m>1) dp[i][j][k][l][m]=min(dp[i][j][k][l][m-2]+1,dp[i][j][k][l][m]);
                        if(m>0) dp[i][j][k][l][m]=min(dp[i][j][k][l][m-1]+1,dp[i][j][k][l][m]);
                        if(i>0) dp[i][j][k][l][m]=min(dp[i-1][j][k][l][m]+1,dp[i][j][k][l][m]);
                        if(l>0) dp[i][j][k][l][m]=min(dp[i][j][k][l-1][m]+1,dp[i][j][k][l][m]);
                        if(k>0) dp[i][j][k][l][m]=min(dp[i][j][k-1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(j>0) dp[i][j][k][l][m]=min(dp[i][j-1][k+1][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0) dp[i][j][k][l][m]=min(dp[i-1][j+1][k][l][m]+1,dp[i][j][k][l][m]);
                        if(k>0) dp[i][j][k][l][m]=min(dp[i][j][k-1][l][m]+1,dp[i][j][k][l][m]);
                        if(j>0) dp[i][j][k][l][m]=min(dp[i][j-1][k][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0) dp[i][j][k][l][m]=min(dp[i+1][j][k-1][l][m]+1,dp[i][j][k][l][m]);
                        if(j>0) dp[i][j][k][l][m]=min(dp[i][j-1][k][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0) dp[i][j][k][l][m]=min(dp[i-1][j][k][l+1][m]+1,dp[i][j][k][l][m]);
                        if(j>0&&m>0) dp[i][j][k][l][m]=min(dp[i][j-1][k][l][m-1]+1,dp[i][j][k][l][m]);
                        if(j>0&&l>0) dp[i][j][k][l][m]=min(dp[i][j-1][k][l-1][m]+1,dp[i][j][k][l][m]);
                        if(j>0&&k>0) dp[i][j][k][l][m]=min(dp[i][j-1][k-1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(j>1) dp[i][j][k][l][m]=min(dp[i][j-2][k+1][l][m]+1,dp[i][j][k][l][m]);
                        if(j>0&&i>0) dp[i][j][k][l][m]=min(dp[i-1][j-1+1][k][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&l>0) dp[i][j][k][l][m]=min(dp[i-1][j][k][l-1+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&k>0) dp[i][j][k][l][m]=min(dp[i-1][j][k-1][l+2][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k+1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>1) dp[i][j][k][l][m]=min(dp[i-2][j+1][k][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&m>0) dp[i][j][k][l][m]=min(dp[i-1][j][k][l+1][m-1]+1,dp[i][j][k][l][m]);
                        if(j>0&&k>0) dp[i][j][k][l][m]=min(dp[i][j-1][k-1][l][m]+1,dp[i][j][k][l][m]);
                        if(j>1) dp[i][j][k][l][m]=min(dp[i][j-2][k][l+1][m]+1,dp[i][j][k][l][m]);
                        if(j>0&&i>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k+1][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&k>0) dp[i][j][k][l][m]=min(dp[i-1][j][k-1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k][l+2][m]+1,dp[i][j][k][l][m]);
                        if(i>1) dp[i][j][k][l][m]=min(dp[i-2][j][k+1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&l>0&&k>0) dp[i][j][k][l][m]=min(dp[i-1][j][k-1][l-1+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&l>0&&j>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k+1][l-1][m]+1,dp[i][j][k][l][m]);
                        if(i>1&&l>0) dp[i][j][k][l][m]=min(dp[i-2][j+1][k][l-1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&m>1) dp[i][j][k][l][m]=min(dp[i-1][j][k][l][m-2]+1,dp[i][j][k][l][m]);
                        if(i>0&&k>1) dp[i][j][k][l][m]=min(dp[i-1][j][k-2][l+2][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>0&&k>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k-1+1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>1&&k>0) dp[i][j][k][l][m]=min(dp[i-2][j+1][k-1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>1) dp[i][j][k][l][m]=min(dp[i-1][j-2][k+2][l][m]+1,dp[i][j][k][l][m]);
                        if(i>1&&j>0) dp[i][j][k][l][m]=min(dp[i-2][j-1+1][k+1][l][m]+1,dp[i][j][k][l][m]);
                        if(i>2) dp[i][j][k][l][m]=min(dp[i-3][j+2][k][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&k>0&&m>0) dp[i][j][k][l][m]=min(dp[i-1][j][k-1][l+1][m-1]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>0&&m>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k+1][l][m-1]+1,dp[i][j][k][l][m]);
                        if(i>1&&m>0) dp[i][j][k][l][m]=min(dp[i-2][j+1][k][l][m-1]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>0&&k>0) dp[i][j][k][l][m]=min(dp[i-1][j-1][k-1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>1&&k>0) dp[i][j][k][l][m]=min(dp[i-2][j][k-1+1][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&j>1) dp[i][j][k][l][m]=min(dp[i-1][j-2][k][l+2][m]+1,dp[i][j][k][l][m]);
                        if(i>1&&j>0) dp[i][j][k][l][m]=min(dp[i-2][j-1][k+1][l+1][m]+1,dp[i][j][k][l][m]);
                        if(i>2) dp[i][j][k][l][m]=min(dp[i-3][j][k+2][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&k>1) dp[i][j][k][l][m]=min(dp[i-1][j][k-2][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&l>1) dp[i][j][k][l][m]=min(dp[i-1][j][k][l-2][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&k>0) dp[i][j][k][l][m]=min(dp[i-1][j][k-1][l][m]+1,dp[i][j][k][l][m]);
                        if(i>1) dp[i][j][k][l][m]=min(dp[i-2][j][k][l][m]+1,dp[i][j][k][l][m]);
                        if(i>0&&l>0&&m>0) dp[i][j][k][l][m]=min(dp[i-1][j][k][l-1][m-1]+1,dp[i][j][k][l][m]);
                        //printf("dp[%d][%d][%d][%d][%d]=%d\n",i,j,k,l,m,dp[i][j][k][l][m]);
                    }
                }
            }
        }
    }   
}
void Search(int now)
{
    for(int i=3;i<=13;i++)
    {
        if(card[i]>=3&&card[i+1]>=3)
        {
            card[i]-=3;card[i+1]-=3;
            Search(now+1);
            int j=i+2;
            while(j<=14&&card[j]>=3)
            {
                card[j]-=3;
                Search(now+1);
                j++;
            }
            for(int k=i;k<j;k++)
            {
                card[k]+=3;
            }
        }
    }
    for(int i=3;i<=12;i++)
    {
        if(card[i]>=2&&card[i+1]>=2&&card[i+2]>=2)
        {
            card[i]-=2;card[i+1]-=2;card[i+2]-=2;
            Search(now+1);
            int j=i+3;
            while(j<=14&&card[j]>=2)
            {
                card[j]-=2;
                Search(now+1);
                j++;
            }
            for(int k=i;k<j;k++)
            {
                card[k]+=2;
            }
        }
    }
    for(int i=3;i<=10;i++)
    {
        if(card[i]>0&&card[i+1]>0&&card[i+2]>0&&card[i+3]>0&&card[i+4]>0)
        {
            card[i]--;card[i+1]--;card[i+2]--;card[i+3]--;card[i+4]--;
            Search(now+1);
            int j=i+5;
            while(j<=14&&card[j]>0)
            {
                card[j]--;
                Search(now+1);
                j++;
            }
            for(int k=i;k<j;k++)
            {
                card[k]++;
            }
        }
    }
    int num4=0,num3=0,num2=0,num1=0,joker=0;
    for(int i=3;i<=15;i++)
    {
        if(card[i]==4) num4++;
        else if(card[i]==3) num3++;
        else if(card[i]==2) num2++;
        else if(card[i]==1) num1++;
    }
    joker=card[16];
    finalans=min(finalans,dp[num4][num3][num2][num1][joker]+now);
    //printf("%d %d %d %d %d %d %d\n",num4,num3,num2,num1,joker,dp[num4][num3][num2][num1][joker]+now,finalans);
}
int main()
{
    //freopen("landlords.in","r",stdin);
    //freopen("landlords.out","w",stdout);
    int x,y;
    T=read();n=read();
    DpBuild();
    while(T--)
    {
        finalans=n;
        memset(card,0,sizeof(card));
        for(int i=1;i<=n;i++)
        {
            x=read();y=read();
            if(x>=3&&x<=13) card[x]++;
            else if(x>=1&&x<=2) card[x+13]++;
            else if(x==0) card[16]++;
        }
        int num4=0,num3=0,num2=0,num1=0,joker=0;
        for(int i=3;i<=15;i++)
        {
            if(card[i]==4) num4++;
            else if(card[i]==3) num3++;
            else if(card[i]==2) num2++;
            else if(card[i]==1) num1++;
        }
        joker=card[16];
        finalans=min(finalans,dp[num4][num3][num2][num1][joker]);
        Search(0);
        printf("%d\n",finalans);
    }
    return 0;
}


以上是关于vijos p1980斗地主/luogu p2540斗地主增强版的主要内容,如果未能解决你的问题,请参考以下文章

建图最短路同余(luogu2662 vijos1054 xjoi2157)

Luogu p1149 / Vijos p1496 火柴棒等式

NOIP 车站分级 (luogu 1983 & codevs 3294 & vijos 1851) - 拓扑排序 - bitset

洛谷—— P1036 选数 || Vijos——选数

noip2015斗地主

洛谷 P1980