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