程序题 P11227 [CSP-J 2024] 扑克牌 【新鲜der题解】

刷洛谷时,我发现了一道有点神金der题目,由于紧缺AC做了亿点点:

# [CSP-J 2024] 扑克牌(民间数据)

## 题目描述

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

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

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

(https://cdn.luogu.com.cn/upload/image_hosting/qj53w3yq.png)

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

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

## 输入格式

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

接下来 n 行:

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

## 输出格式

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

## 样例 #1

### 样例输入 #1
1
SA

### 样例输出 #1
51

## 样例 #2

### 样例输入 #2
4
DQ
H3
DQ
DT

### 样例输出 #2
49

## 提示

**【样例 1 解释】**

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

**【样例 2 解释】**

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

**【样例 3 解释】**

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

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

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

**【数据范围】**

对于所有测试数据,保证:1 <= n <= 52,输入的 n 个字符串每个都代表一张合法的扑克牌,即字符串长度为 2,且第一个字符为 D C H S 中的某个字符,第二个字符为 A 2 3 4 5 6 7 8 9 T J Q K 中的某个字符。

以上是题目,这个题目针对的应该是C++新手,所以我先用二阶学习的知识写了以下代码:

#include<iostream>
using namespace std;
int main(){
    int a[15]={},b[15]={},c[15]={},d[15]={};
    int n;
    cin>>n;
    char x,y;
    for(int i=0;i<n;i++){
        cin>>x>>y;
        if(x=='D'){
            if(y=='A'){
                a[1]++;
            }else if(y=='T'){
                a[10]++;
            }else if(y=='J'){
                a[11]++;
            }else if(y=='Q'){
                a[12]++;
            }else if(y=='K'){
                a[13]++;
            }else{
                a[y-'0']++;
            }
        }else if(x=='C'){
            if(y=='A'){
                b[1]++;
            }else if(y=='T'){
                b[10]++;
            }else if(y=='J'){
                b[11]++;
            }else if(y=='Q'){
                b[12]++;
            }else if(y=='K'){
                b[13]++;
            }else{
                b[y-'0']++;
            }
        }else if(x=='H'){
            if(y=='A'){
                c[1]++;
            }else if(y=='T'){
                c[10]++;
            }else if(y=='J'){
                c[11]++;
            }else if(y=='Q'){
                c[12]++;
            }else if(y=='K'){
                c[13]++;
            }else{
                c[y-'0']++;
            }
        }else if(x=='S'){
            if(y=='A'){
                d[1]++;
            }else if(y=='T'){
                d[10]++;
            }else if(y=='J'){
                d[11]++;
            }else if(y=='Q'){
                d[12]++;
            }else if(y=='K'){
                d[13]++;
            }else{
                d[y-'0']++;
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=13;i++){
        if(a[i]==0){
            cnt++;
        }if(b[i]==0){
            cnt++;
        }if(c[i]==0){
            cnt++;
        }if(d[i]==0){
            cnt++;
        }
    }
    cout<<cnt;
    return 0;
}

以上代码看着比较繁琐,我又用了二维数组等知识点优化了一下:

#include<bits/stdc++.h>
using namespace std;
int a[5][14];
signed main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		string s;
		cin>>s;
		int cnt1=0,cnt2=0;
		if(s[0]=='D')
		{
			cnt1=1;
		}
		if(s[0]=='C')
		{
			cnt1=2;
		}
		if(s[0]=='H')
		{
			cnt1=3;
		}
		if(s[0]=='S')
		{
			cnt1=4;
		}
		if(s[1]=='A')
		{
			cnt2=1;
		}
		if(s[1]>='2'&&s[1]<='9')
		{
			cnt2=s[1]-'0';
		}
		if(s[1]=='T')
		{
			cnt2=10;
		}
		if(s[1]=='J')
		{
			cnt2=11;
		}
		if(s[1]=='Q')
		{
			cnt2=12;
		}
		if(s[1]=='K')
		{
			cnt2=13;
		}
		a[cnt1][cnt2]=1;
	}
	int cnt=0;
	for(int i=1;i<=4;i++)
	{
		for(int j=1;j<=13;j++)
		{
			cnt+=a[i][j];
		}
	}
	printf("%d",52-cnt);
}

由于优化以后还是比较复杂,so,我又优化了一下(杜绝废话:

#include <bits/stdc++.h>
using namespace std;
int main() {
	set <string> S;
	int n;cin >> n;
	for (int i=1;i<=n;i++) {
		string s;
		cin >> s;
		S.insert(s);
	}
	cout << 52-S.size() << endl;
	return 0;
}

以上是我所有思路,如果有建议或新方法可以在评论区分享哦,制作不易,还望给个三连,谢谢浏览!

提供的引用内容中未涉及“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扑克牌相关问”可能有不同的具体要求,需要根据具体问进行调整。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值