牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃、紅心、梅花、 方片的 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);
}
}