【NOIP2015提高組】鬥地主
題目背景
NOIP2015 提高組 Day1 T3
題目描述
牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃、紅心、梅花、方片的A到K加上大小王的共54張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關係根據牌的數碼錶示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色並不對牌的大小產生影響。每一局遊戲中,一副手牌由 n 張牌組成。遊戲者每次可以根據規定的牌型進行出牌,首先打光自己的手牌一方取得遊戲的勝利。 現在,牛牛隻想知道,對於自己的若干組手牌,分別最少需要多少次出牌可以將它們打光。請你幫他解決這個問題。 需要注意的是,本題中游戲者每次可以出手的牌型與一般的鬥地主相似而略有不同。 具體規則如下:
輸入格式
第一行包含用空格隔開的 2 個正整數 T ,n ,表示手牌的組數以及每組手牌的張數。 接下來 T 組資料,每組資料 n 行,每行一個非負整數對 ai,bi ,表示一張牌,其中 ai 表示牌的數碼,bi 表示牌的花色,中間用空格隔開。特別的,我們用 1 來表示數碼 A,11 表示數碼 J,12 表示數碼 Q ,13 表示數碼 K ;黑桃、紅心、梅花、方片分別用 1~4 來表示;小王的表示方法為 0 1,大王的表示方法為 0 2 。
輸出格式
輸出共 T 行,每行一個整數,表示打光第 i 組手牌的最少次數。 樣例資料 1 輸入
1 8 7 4 8 4 9 1 10 4 11 1 5 1 1 4 1 1
輸出
3
樣例資料 2 輸入
1 17 12 3 4 3 2 3 5 4 10 2 3 3 12 2 0 1 1 3 10 1 6 2 12 1 11 3 5 2 12 4 2 2 7 2
輸出
6
備註 【樣例1說明】 共有 1 組手牌,包含 8 張牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通過打單順子(方片7,方片8,黑桃9,方片10,黑桃J),單張牌(黑桃5)以及對子牌(黑桃A以及方片A)在3次內打光。 【資料範圍】 對於不同的測試點,我們約定手牌組數 T 與張數 n 的規模如下: 資料保證:所有的手牌都是隨機生成的。
解析:
大模擬?不不不,普通搜尋就行了。 考慮沒有順子的情況,那麼就可以貪心的進行出牌,出牌優先順序為順子>四帶二>四帶一>三帶二>三帶一>對子>單牌。因為出一次優先順序大的組合一定有多個優先順序小的組合組成的,所以貪心一定是是對的。 但是有了順子後,就不能證明貪心是對的,就直接搜尋順子是哪些,然後更新答案,必要的剪枝是肯定要加的。
程式碼:
#include <bits/stdc++.h>
using namespace std;
const int card[5]={0,5,3,2};
const int Max=16;
int n,m,ans,x,y,t;
int a[Max],sum[Max];
inline int calc()
{
int tot=0;
memset(sum,0,sizeof(sum));
for(int i=0;i<=14;i++) if(i^1) sum[a[i]]++;
while(sum[4]&&sum[2]>=2) tot++,sum[4]--,sum[2]-=2;
while(sum[4]&&sum[1]>=2) tot++,sum[4]--,sum[1]-=2;
while(sum[3]&&sum[2]) tot++,sum[3]--,sum[2]--;
while(sum[3]&&sum[1]) tot++,sum[3]--,sum[1]--;
return tot+sum[1]+sum[2]+sum[3]+sum[4];
}
inline void dfs(int step)
{
if(step>=ans) return;
ans=min(ans,step+calc());
for(int same=3;same;same--)
for(int i=3;i<=13;i++)
{
int j=i;
while(a[j]>=same&&j<=14) j++;j--;
if(j-i+1<card[same]) continue;
for(int k=i;k<=i+card[same]-2;k++) a[k]-=same;
for(int k=i+card[same]-1;k<=j;k++) a[k]-=same,dfs(step+1);
for(int k=i;k<=j;k++) a[k]+=same;
}
}
int main()
{
scanf("%d%d",&t,&n);
while(t--)
{
memset(a,0,sizeof(a)),ans=n;
for(int i=1;i<=n;i++) scanf("%d%d",&x,&y),x=x==1?14:x ,a[x]++;
dfs(0),printf("%d\n",ans);
}
return 0;
}