鏈接:https://ac.nowcoder.com/acm/contest/3036/G
來源:牛客網
題目描述
這次是一個成年男性,他正在玩弄着手上的撲克牌,紙牌在他手中翻飛着,如同空中飛舞的蝴蝶。
「死後居然被計入英靈座,現在居然還被召喚到這裏,真是很奇妙啊」他先發言了「我並無任何武藝,但對數學方面略有心得,我即爲七騎之中的魔術師(caster)」
「嗚」他所說的信息實在太少太少了,我根本沒法判別他的真名
「你們能到達這裏必是多少有些許智慧的」他直接把17張撲克牌飛了過來。撲克牌如同利刃一般飛來,但並沒有故意瞄準我,這也叫沒有什麼武藝麼
「我對賭博很有興趣,但是這紙牌遊戲也只是無趣的記憶遊戲。撿起這些紙牌吧。」他從牌堆裏面也抽出了17張牌「和我玩一場遊戲,贏了就可以過去,輸了就永遠在這複數的空間裏徘徊」
(規則與實際鬥地主有出入,請以本題題面爲準)
給出17張牌,計算剛開局總共有多少種不同的出牌方案。
牌的種類,順序(從小到大):
3 4 5 6 7 8 9 0(代表10) J Q K A 2
出牌方式:
單個牌:單張牌,比如:3
對子:兩張種類相同的牌,比如:2,2
炸彈:四張種類相同的牌,比如:6,6,6,6
三帶一:有兩種牌,一種牌有三張,另一種牌有一張,比如:3,3,3,A
三帶二:有兩種牌,一種牌有三張,另一種牌有兩張,比如:3,3,3,A,A
五單順子:五張連續的單牌,且五張牌種類各不相同。比如:4,5,6,7,8。五單順子的牌的種類可以包括 2,比如:J,Q,K,A,2,也是五單順子。注意:A,2,3,4,5,不是五單順子,3,4,5,6,6,也不是五單順子
由於花色的原因,即使是相同種類的牌,也是不同的牌
輸入描述:
第一行一個整數T(1 ≤ T ≤ 100),代表T組樣例,
對於每組樣例,輸入一行,每行輸入一個僅由{‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘0’, ‘J’, ‘Q’, ‘K’, ‘A’, ‘2’}字符組成的字符串str,(|str|==17)。其中|str|代表字符串的長度。
題目保證每種牌最多四張(代表四種花色)
輸出描述:
對於每一行輸入,輸出有多少種不同的出牌方案
示例1
輸入
1
AAAA234567890JQKK
輸出
105
說明
單個牌:17種,A,A,A,A,2,3,4,5,6,7,8,9,0,J,Q,K,K
對子:7種,AA,AA,AA,AA,AA,AA,KK(注意A的不同)
炸彈:1種,AAAA
三帶一:52種
三帶二:4種,AAAKK, AAAKK, AAAKK, AAAKK
五單順子:24種
總共:105種
思路
因爲有除了數字以外的其他字符所以就不能用整型去輸入
於是乎我使用了快讀(快速讀入)的變式
因爲這些字符其實是有大小順序的,所以通過判斷字符給他們配對上相應大小的數值
然後由於看別人的解析太多了…看到這種題就想到要把他們排好序
就使用了qsort函數從小到大排好
接下來就是的排列組合的高中知識
5單順子這個由於我沒審題…還以爲是打出順子…就在想單牌和對牌的順子以及大於等於5的要怎麼解決.等我寫出來再看題才發現…淦
代碼
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int read() {
char a = getchar();
switch (a) {
default:return a - '2';
case '0':return 8;
case 'J':return 9;
case 'Q':return 10;
case 'K':return 11;
case 'A':return 12;
case '2':return 13;
}
}
int cmp(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
int sum = 1;
int contain = 0;
int mun[17];
int main() {
int t;
scanf("%d", &t);getchar();
int num = 0;
int four = 0, three = 0, two = 0, one = 0;
while (t--) {
memset(mun, 0, sizeof(int) * 17);
for (int i = 0; i < 17; i++)
mun[i] = read();
getchar();//忘記吸收enter鍵
qsort(mun, 17, sizeof(int), cmp);
for (int i = 0, j; i < 16; i++) {
for (j = 1, num = 1; j <= 4;j++, i++)
if (mun[i] == mun[i + 1]) num++;
else break;
if (num == 4) four++;
if (num == 3) three++;
if (num == 2) two++;
if (num == 1) one++;
}
one++;
contain += 17;
contain += two + three * 3 + four * 6;
contain += four;
contain += three * 14 + four * 4 * 13;
contain += three * (two + four * 6 + (three - 1) * 3) + four * 4 * (two + three * 3 + (four - 1) * 6);
int times[17] = { 0 };
for (int i = 0, j = 0, k = 0; i < 17; i++)
if (mun[i] == mun[j]) times[k]++;
else {
if (mun[i] == mun[j] + 1) times[++k]++;
else times[++++k]++;
j = i;
}
for (int i = 0;i < 13;i++) {
for (int j = 0;j <= 4;j++)
sum *= times[i + j];
contain += sum;
sum = 1;
}
printf("%d\n", contain);//沒加換行一直報錯
contain = num = one = two = three = four = 0;//忘記歸零
}
return 0;
}
總結
感覺自己思路和解題方式有了提高,奈何將思路轉化爲代碼的能力還是欠缺,寫的過程基本上都是摸魚,單純的在想不知道要怎麼把思路弄成代碼的形式.以後可能要多練練
操作過程還是很多細節沒做好花了很多時間,比如沒有將enter
吸收,輸出沒有\n
沒有將數值歸零
代碼還可以再省一點,把for (int i = 0, j; i < 16; i++)
和for (int i = 0, j = 0, k = 0; i < 17; i++)
這兩個判斷條件合並可以減少循環次數