2019年廣東工業大學騰訊杯新生程序設計競賽(同步賽)G-虛數的紙牌

鏈接: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函數從小到大排好
接下來就是CnkC^k_n的排列組合的高中知識

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++)這兩個判斷條件合並可以減少循環次數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章