洛谷P11227 [CSP-J 2024] 扑克牌

P11227 [CSP-J 2024] 扑克牌

题目描述

小 P 从同学小 Q 那儿借来一副 nnn 张牌的扑克牌。

本题中我们不考虑大小王,此时每张牌具有两个属性:花色和点数。花色共有 444 种:方片、草花、红桃和黑桃。点数共有 131313 种,从小到大分别为 A23456789TJQK\tt{A 2 3 4 5 6 7 8 9 T J Q K}A23456789TJQK。注意:点数 101010 在本题中记为 T\tt TT

我们称一副扑克牌是完整的,当且仅当对于每一种花色和每一种点数,都恰好有一张牌具有对应的花色和点数。由此,一副完整的扑克牌恰好有 4×13=524 \times 13 = 524×13=52 张牌。以下图片展示了一副完整的扑克牌里所有的 52 张牌。

小 P 借来的牌可能不是完整的,为此小 P 准备再向同学小 S 借若干张牌。可以认为小 S 每种牌都有无限张,因此小 P 可以任意选择借来的牌。小 P 想知道他至少得向小 S 借多少张牌,才能让从小 S 和小 Q 借来的牌中,可以选出 525252 张牌构成一副完整的扑克牌。

为了方便你的输入,我们使用字符 D\tt DD 代表方片,字符 C\tt CC 代表草花,字符 H\tt HH 代表红桃,字符 S\tt SS 代表黑桃,这样每张牌可以通过一个长度为 222 的字符串表示,其中第一个字符表示这张牌的花色,第二个字符表示这张牌的点数,例如 CA\tt{CA}CA 表示草花 A\tt AAST\tt{ST}ST 表示黑桃 T\tt TT(黑桃 10)。

输入格式

输入的第一行包含一个整数 nnn 表示牌数。

接下来 nnn 行:

每行包含一个长度为 222 的字符串描述一张牌,其中第一个字符描述其花色,第二个字符描述其点数。

输出格式

输出一行一个整数,表示最少还需要向小 S 借几张牌才能凑成一副完整的扑克牌。

输入输出样例 #1

输入 #1

1
SA

输出 #1

51

输入输出样例 #2

输入 #2

4
DQ
H3
DQ
DT

输出 #2

49

说明/提示

【样例 1 解释】

这一副牌中包含一张黑桃 A\tt AA,小 P 还需要借除了黑桃 A\tt AA 以外的 51 张牌以构成一副完整的扑克牌。

【样例 2 解释】

这一副牌中包含两张方片 Q\tt QQ、一张方片 T\tt TT(方片 10)以及一张红桃 3,小 P 还需要借除了红桃 3、方片 T\tt TT 和方片 Q\tt QQ 以外的 494949 张牌。

【样例 3 解释】

见选手目录下的 poker/poker3.in 与 poker/poker3.ans。

这一副扑克牌是完整的,故不需要再借任何牌。

该样例满足所有牌按照点数从小到大依次输入,点数相同时按照方片、草花、红桃、黑桃的顺序依次输入。

【数据范围】

对于所有测试数据,保证:1≤n≤521 \leq n \leq 521n52,输入的 nnn 个字符串每个都代表一张合法的扑克牌,即字符串长度为 222,且第一个字符为 DCHS\tt{D C H S}DCHS 中的某个字符,第二个字符为 A23456789TJQK\tt{A 2 3 4 5 6 7 8 9 T J Q K}A23456789TJQK 中的某个字符。

::cute-table{tuack}

测试点编号n≤n \leqn特殊性质
111111A
2∼42\sim 424525252^
5∼75\sim 757^B
8∼108\sim 10810^

特殊性质 A:保证输入的 nnn 张牌两两不同。

特殊性质 B:保证所有牌按照点数从小到大依次输入,点数相同时按照方片、草花、红桃、黑桃的顺序依次输入。

为了解决这个问题,我们需要计算小P需要从小S借多少张牌才能凑齐一副完整的扑克牌。一副完整的扑克牌由52张不同的牌组成,每种花色和点数的组合各一张。关键在于统计小P已经拥有的不同牌的数量,然后用52减去这个数量即可得到需要借的牌数。

方法思路

  1. 问题分析:问题要求从已有的牌中找出缺失的牌的种类数。每张牌由花色和点数唯一确定,完整的牌组共有52种不同的组合。
  2. 关键观察:由于小S可以提供任意数量的任何牌,只需计算已有牌中不同牌的数量,缺失的牌数即为52减去这个数量。
  3. 算法选择:使用集合(Set)来存储已拥有的牌,利用集合自动去重的特性来统计不同牌的数量。
  4. 复杂度分析:插入n个元素到集合中的时间复杂度为O(n log n),适用于n的最大值52,效率很高。

解决代码

#include <iostream>
#include <set>
#include <string>
using namespace std;

int main() {
    int n;
    cin >> n;
    set<string> cards;
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        cards.insert(s);
    }
    cout << 52 - cards.size() << endl;
    return 0;
}

代码解释

  1. 输入处理:首先读取牌的数量n,然后读取n张牌的描述字符串。
  2. 存储与去重:使用集合cards来存储每张牌的字符串,集合自动处理重复项,确保每种牌只计数一次。
  3. 结果计算:输出52减去集合的大小,即缺失的牌数,也就是需要从小S借的牌数。
提供的引用内容中未涉及“01:CSP - J2024 - 1扑克牌相关问题”,所以无法依据引用给出使用C语言解决该问题的方法。一般来说,使用C语言解决扑克牌相关问题,通常会涉及到以下几个步骤: ### 定义扑克牌数据结构 可以使用结构体来表示扑克牌,包含花色和点数等息。 ```c #include <stdio.h> #include <stdlib.h> // 定义扑克牌结构体 typedef struct { int suit; // 花色,例如 0-3 表示不同花色 int rank; // 点数,例如 1-13 表示 A-K } Card; ``` ### 初始化扑克牌 ```c // 初始化一副扑克牌 void initializeDeck(Card deck[]) { int index = 0; for (int suit = 0; suit < 4; suit++) { for (int rank = 1; rank <= 13; rank++) { deck[index].suit = suit; deck[index].rank = rank; index++; } } } ``` ### 洗牌 ```c #include <time.h> // 洗牌函数 void shuffleDeck(Card deck[]) { srand(time(NULL)); for (int i = 51; i > 0; i--) { int j = rand() % (i + 1); Card temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } ``` ### 发牌 ```c // 发牌函数 void dealCards(Card deck[], int numPlayers, int numCardsPerPlayer) { for (int player = 0; player < numPlayers; player++) { printf("Player %d's cards:\n", player + 1); for (int i = 0; i < numCardsPerPlayer; i++) { int cardIndex = player * numCardsPerPlayer + i; printf("Suit: %d, Rank: %d\n", deck[cardIndex].suit, deck[cardIndex].rank); } printf("\n"); } } ``` ### 主函数 ```c int main() { Card deck[52]; initializeDeck(deck); shuffleDeck(deck); int numPlayers = 4; int numCardsPerPlayer = 5; dealCards(deck, numPlayers, numCardsPerPlayer); return 0; } ``` 以上代码是一个简单的扑克牌处理示例,实际的“01:CSP - J2024 - 1扑克牌相关问题”可能有不同的具体要求,需要根据具体问题进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信奥源老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值