刷洛谷时,我发现了一道有点神金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;
}
以上是我所有思路,如果有建议或新方法可以在评论区分享哦,制作不易,还望给个三连,谢谢浏览!