牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、 方片的 A 到 K 加上大小王的共 54 张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10< J< Q< K< A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由 n 张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:
本题数据较水,请上https://vijos.org/p/1980测评
Input Format
输入文件名为 landlords.in。
第一行包含用空格隔开的2个正整数T,n,表示手牌的组数以及每组手牌的张数。
接下来T组数据,每组数据n行,每行一个非负整数对ai,bi,表示一张牌,其中ai表示牌的数码,bi表示牌的花色,中间用空格隔开。特别的,我们用 1 来表示数码 A,11 表示数码 J,12 表示数码 Q,13 表示数码 K;黑桃、红心、梅花、方片分别用 1-4 来表示;小王的表示方法为 0 1,大王的表示方法为 0 2。
Output Format
输出文件名为 landlords.out。 共 T 行,每行一个整数,表示打光第i组手牌的最少次数。
【题解】
贪心 搜索(据说是有bug的但是是随机数据就能过)
先搜索顺子的每种出牌情况 (由于顺子不包括2,所以把整副牌的数字整体后移1变13,其余变为i-1,这样比较方便处理)
对于每种情况处理剩下的牌不用顺子最少几次出完(贪心)
贪心处理过程
1.四带两对 2.四带两张 3.四带一对 4.三代二 5.三带一 6.炸、三张、对子、单牌
王炸当做对牌处理
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int a[50],num[5],i,j,k,l,m,n,T,cnt,col,ans;
void dfs(int kk)
{
if (kk>=ans) return;
int i,j,k,l,tot=0;
memset(num,0,sizeof(num));
for (i=0;i<=13;i++) num[a[i]]++;
for (;num[4]&&num[2]>1;num[4]--,num[2]-=2,tot++);
for (;num[4]&&num[1]>1;num[4]--,num[1]-=2,tot++);
for (;num[4]&&num[2];num[4]--,num[2]--,tot++);
for (;num[3]&&num[2];num[3]--,num[2]--,tot++);
for (;num[3]&&num[1];num[3]--,num[1]--,tot++);
tot+=(num[1]+num[2]+num[3]+num[4]);
if (kk+tot<ans) ans=kk+tot;
for (i=2;i<=13;i++)
{
for (j=i;a[j]>=3;j++);
if(j-i>=2)
{
for (l=i+1;l<=j-1;l++)
{
for (k=i;k<=l;k++) a[k]-=3;
dfs(kk+1);
for (k=i;k<=l;k++) a[k]+=3;
}
}
}
for (i=2;i<=13;i++)
{
for (j=i;a[j]>=2;j++);
if(j-i>=3)
{
for (l=i+2;l<=j-1;l++)
{
for (k=i;k<=l;k++) a[k]-=2;
dfs(kk+1);
for (k=i;k<=l;k++) a[k]+=2;
}
}
}
for (i=2;i<=13;i++)
{
for (j=i;a[j]>=1;j++);
if(j-i>=5)
{
for (l=i+4;l<=j-1;l++)
{
for (k=i;k<=l;k++) a[k]-=1;
dfs(kk+1);
for (k=i;k<=l;k++) a[k]+=1;
}
}
}
}
int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
for (scanf("%d%d",&T,&n);T;T--)
{
memset(a,0,sizeof(a));
int x,y;
for (i=1;i<=n;i++)
{
scanf("%d%d",&cnt,&col);
if(cnt==1) cnt=13; else if(cnt!=0) cnt--;a[cnt]++;
}
ans=1e9;dfs(0);
printf("%d\n",ans);
}
}