P2668 鬥地主
阿新 • • 發佈:2017-05-22
其中 tool -- 正整數 現在 ring left hang ==
輸入樣例#1:
P2668 鬥地主
題目描述
牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃、紅心、梅花、方片的A到K加上大小王的共54張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關系根據牌的數碼表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色並不對牌的大小產生影響。每一局遊戲中,一副手牌由n張牌組成。遊戲者每次可以根據規定的牌型進行出牌,首先打光自己的手牌一方取得遊戲的勝利。
現在,牛牛只想知道,對於自己的若幹組手牌,分別最少需要多少次出牌可以將它們打光。請你幫他解決這個問題。
需要註意的是,本題中遊戲者每次可以出手的牌型與一般的鬥地主相似而略有不同。
具體規則如下:
輸入輸出格式
輸入格式:
第一行包含用空格隔開的2個正整數T和n,表示手牌的組數以及每組手牌的張數。
接下來T組數據,每組數據n行,每行一個非負整數對aibi表示一張牌,其中ai示牌的數碼,bi表示牌的花色,中間用空格隔開。特別的,我們用1來表示數碼A,11表示數碼J,12表示數碼Q,13表示數碼K;黑桃、紅心、梅花、方片分別用1-4來表示;小王的表示方法為01,大王的表示方法為02。
輸出格式:
共T行,每行一個整數,表示打光第i手牌的最少次數。
輸入輸出樣例
1 8 7 4 8 4 9 1 10 4 11 1 5 1 1 4 1 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輸出樣例#2:
6
說明
樣例1說明
共有1組手牌,包含8張牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通過打單順子(方片7,方片8,黑桃9,方片10,黑桃J),單張牌(黑桃5)以及對子牌(黑桃A以及方片A)在3次內打光。
對於不同的測試點, 我們約定手牌組數T與張數n的規模如下:
數據保證:所有的手牌都是隨機生成的。
分析:深搜。深搜順子出現的各種情況,然後加上 三帶一,三帶二,四帶一,四帶二,四帶兩個對子,單出一張牌,兩張牌,三張牌,四張牌的次數
1 #include<cstdio> 2 #include<cstring> 3 4 using namespace std; 5 const int N = 20; 6 7 int puke[N]; 8 int num[N]; 9 int t,n,ans; 10 11 int chupai() 12 { 13 memset(num,0,sizeof(num)); 14 for(int i=0;i<=13;++i) 15 num[puke[i]]++; 16 int tot = 0; 17 while(num[4] && num[2]>1) 18 { 19 num[4]--; 20 num[2] -= 2; 21 tot++; 22 } 23 while(num[4] && num[1]>1) 24 { 25 num[4]--; 26 num[1] -= 2; 27 tot++; 28 } 29 while(num[4] && num[2]) 30 { 31 num[4]--; 32 num[2]--; 33 tot++; 34 } 35 while(num[3] && num[2]) 36 { 37 num[3]--; 38 num[2]--; 39 tot++; 40 } 41 while(num[3] && num[1]) 42 { 43 num[3]--; 44 num[1]--; 45 tot++; 46 } 47 return tot + num[1] + num[2] + num[3] + num[4]; 48 } 49 50 void dfs(int step) 51 { 52 if(step>=ans) return; 53 int tmp = chupai(); 54 if(tmp+step<ans) ans = tmp+step; 55 for(int i=2;i<=13;++i) //三個的順子 56 { 57 int j = i; 58 while(puke[j]>=3) j++; 59 if(j-i>=2) 60 for(int p=i+1;p<=j-1;++p) 61 { 62 for(int k=i;k<=p;++k) 63 puke[k] -= 3; 64 dfs(step+1); 65 for(int k=i;k<=p;++k) 66 puke[k] += 3; 67 } 68 } 69 for(int i=2;i<=13;++i) //兩個的順子 70 { 71 int j = i; 72 while(puke[j]>=2) j++; 73 if(j-i>=3) 74 for(int p=i+2;p<=j-1;++p) 75 { 76 for(int k=i;k<=p;++k) 77 puke[k] -= 2; 78 dfs(step+1); 79 for(int k=i;k<=p;++k) 80 puke[k] += 2; 81 } 82 } 83 for(int i=2;i<=13;++i) //一個的順子 84 { 85 int j = i; 86 while(puke[j]>=1) j++; 87 if(j-i>=5) 88 for(int p=i+4;p<=j-1;++p) 89 { 90 for(int k=i;k<=p;++k) 91 puke[k]--; 92 dfs(step+1); 93 for(int k=i;k<=p;++k) 94 puke[k]++; 95 } 96 } 97 } 98 int main() 99 { 100 freopen("landlords.in","r",stdin); 101 freopen("landlords.out","w",stdout); 102 scanf("%d%d",&t,&n); 103 while(t--) 104 { 105 memset(puke,0,sizeof(puke)); 106 for(int i=1;i<=n;++i) 107 { 108 int x,y; 109 scanf("%d%d",&x,&y); 110 if(x==1) x = 13; 111 else if(x) x--; 112 puke[x]++; 113 } 114 ans = 99999999; 115 dfs(0); 116 printf("%d\n",ans); 117 } 118 return 0; 119 }
P2668 鬥地主