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函数从小到大排好
接下来就是 C n k C^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++)这两个判断条件合并可以减少循环次数

发布了24 篇原创文章 · 获赞 11 · 访问量 2187

猜你喜欢

转载自blog.csdn.net/weixin_45696526/article/details/105550748