首页 > 试题广场 >

小红玩纸牌

[编程题]小红玩纸牌
  • 热度指数:752 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小红最近迷上了纸牌。纸牌有黑桃(Spade)、红桃(Heart)、方块(Diamond)、梅花(Club)四种花色,并且每张纸牌上面写了一个正整数。小红拿到了许多牌,准备玩以下游戏:

每次操作在这堆牌中任取5张牌,计算这5张牌的分数,然后将其丢弃(丢弃的牌不可再次选取)。
为了简化,本题仅计算同花顺这一牌型:即取出的5张牌构成同花顺,则可以获得1分。其他牌型均不得分。
所谓同花顺,即五张牌花色相同,且排序后满足a_{i}+1=a_{i+1}

小红想知道,经过若干次操作后,自己最多可以得到多少分?
请注意,同一个牌型可能出现多次!

输入描述:
第一行输入一个正整数n,代表牌堆中牌的种类(如果两张牌的花色或数值不同,则认为种类不同)。
接下来的n行,每行输入两个正整数:a_icnt_i和一个字符c_i,分别代表每种牌的大小、数量以及花色。
1\leq n \leq 10^5
1\leq a_i,cnt_i \leq 10^9
c_i∈{'S','H','D','C'},代表扑克牌的四种花色:黑桃(Spade)、红桃(Heart)、方块(Diamond)、梅花(Club)。
保证每个种类的牌在输入中只出现了一次。


输出描述:
一个整数,代表小红可以最多获得的分数。
示例1

输入

6
1 1 S
2 2 S
3 2 S
4 2 S
5 2 S
1 10 H

输出

1

说明

可以取到一个同花顺:[1S,2S,3S,4S,5S]。虽然有10个红桃1,但无法和其他牌凑成同花顺
示例2

输入

6
1 1 H
2 2 H
3 2 H
4 2 H
5 2 H
6 10 H

输出

2

说明

可以取两次:[1H,2H,3H,4H,5H][2H,3H,4H,5H,6H]
""" 功能:扑克牌顺子计分程序 核心逻辑:按花色(S黑桃、H红桃、D方块、C梅花)统计“连续5个数字的顺子”得分 计分规则:每个顺子得分为5张牌对应数量的最小值,用掉的牌数量需扣除,最终累加所有花色总得分 输入格式: 1. 第一行:整数n(牌的总组数) 2. 后续n行:每行3个元素(牌数字 数量 花色),例:"3 2 H" 表示红桃3有2张 输出格式:所有有效顺子的总得分 """ def main(): """读取输入并初始化牌组存储结构""" n = int(input()) poker = { "S": {}, "H": {}, "D": {}, "C": {}, } """循环读取n组牌信息,存入对应花色的字典""" for i in range(n): x, num, color = input().split(" ") poker[color][int(x)] = int(num) total = 0 """遍历每个花色,单独计算该花色的顺子得分""" for color in "SHDC": ans = 0 nums = poker[color] keys = list(nums.keys()) keys = sorted(keys) """遍历每个数字k,尝试以k为起点组成“k~k+4”的5张连续顺子""" for k in keys: cur = [nums[k]] """检查k+1到k+4是否都存在且数量>0(凑齐5张连续牌)""" for i in range(1, 5): if (k + i) in nums and nums[k + i] > 0: cur.append(nums[k + i]) else: break """若凑成顺子,计算得分并扣除用掉的牌""" if len(cur) == 5: grade = min(cur) for i in range(5): if (k + i) in nums: nums[k + i] -= grade ans += grade total += ans print(total)
发表于 2025-11-10 07:24:18 回复(1)
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

// 统一处理单个花色的逻辑
void processSuit(map<int, int>& suit, long long& score) {
    for (auto it = suit.begin(); it != suit.end(); ) {
        int x = it->first;
        bool isStraight = true;

        // 检查x+1到x+4是否存在(避免使用operator[],防止自动插入)
        for (int i = 1; i <= 4; ++i) {
            if (suit.find(x + i) == suit.end()) {//如果find不到,会返回.end()
                isStraight = false;
                break;
            }
        }

        if (isStraight) {//存在同花顺
            // 计算最小数量(确保所有数量非负)
            int minCnt = it->second;
            if (minCnt < 0) minCnt = 0; // 防御性检查

            for (int i = 1; i <= 4; ++i) {
                int cnt = suit.at(x + i); // 使用at(),不存在会抛异常(便于调试)
                if (cnt < 0) cnt = 0;
                minCnt = min(minCnt, cnt);
            }

            // 只有正数量才加分
            if (minCnt > 0) {
                score += minCnt;

                // 减去数量,确保不小于0
                it->second = max(0, it->second - minCnt);
                for (int i = 1; i <= 4; ++i) {
                    suit[x + i] = max(0, suit.at(x + i) - minCnt);
                }
            }
        }

        // 更新迭代器(删除数量为0的牌)
        if (it->second == 0) {
            it = suit.erase(it);
        } else {
            ++it;
        }
    }
}

int main() {
    int n;//牌堆中牌的种类(如果两张牌的花色或数值不同,则认为种类不同)。
    cin >> n;
    //思考:怎么存储
    //4个map<int,int>,前面int是“大小”,后面int是数量
    map<int, int> S;
    map<int, int> H;
    map<int, int> D;
    map<int, int> C;
    for (int i = 0; i < n; i++) {
        //每行输入两个正整数:a_i和cnt_i和一个字符c_i,分别代表每种牌的大小、数量以及花色。
        int a_i = 0, cnt_i = 0;
        char c_i;//c_i∈{'S','H','D','C'}
        cin >> a_i >> cnt_i >> c_i;
        if (c_i == 'S') {
            S[a_i] = cnt_i;
        } else if (c_i == 'H') {
            H[a_i] = cnt_i;
        } else if (c_i == 'D') {
            D[a_i] = cnt_i;
        } else {
            C[a_i] = cnt_i;
        }
    }
    //查询时就遍历某个花色,看存不存在同花顺
    long long score = 0;//防止溢出
    processSuit(S, score);
    processSuit(H, score);
    processSuit(D, score);
    processSuit(C, score);

    cout << score;
    return 0;
}


发表于 2025-11-04 20:28:07 回复(0)
def main():
    n = int(input())
    poker = {
        "S": {},
        "H": {},
        "D": {},
        "C": {},
    }
    for i in range(n):
        x, num, color = input().split(" ")
        poker[color][int(x)] = int(num)

    total = 0
    for color in "SHDC":
        ans = 0
        grade = 0
        nums = poker[color]
        # 以数字 k 开头的顺子
        keys = list(nums.keys())
        keys = sorted(keys)
        for k in keys:
            cur = [nums[k]]

            # 是否都存在
            for i in range(1, 5):
                if (k + i) in nums and nums[k + i] > 0:
                    cur.append(nums[k + i])
                else:
                    break

            # 都存在就算分
            if len(cur) == 5:
                grade = min(cur)
                # 拿走牌
                for i in range(5):
                    if (k + i) in nums:
                        nums[k + i] -= grade
                ans += grade
        total += ans

    print(total)
​
发表于 2025-09-13 20:10:12 回复(0)
#include <bits/stdc++.h>
#define ll long long
using namespace std;

struct Card {
    ll val;
    ll count;
    char style;
    Card(ll val, ll count, char style) : val(val), count(count), style(style) {}
};


void checkStraightFlush(vector<Card>& cards, ll& ans) {
    
    ll size = cards.size();
    if (size < 5) return;

    // 按牌值升序排序
    sort(cards.begin(), cards.end(), [](const Card & x1, const Card & x2) {
        return x1.val < x2.val;
    });
    ll i=0;
    while (i <= size - 5) {
        while(cards[i].count<=0) i++;
        ll begVal = cards[i].val;
        bool isStraight = true;
        ll minCount=cards[i].count;//取最小牌数量(代表可以消掉的最少组)
        for (ll j = 1; j < 5; ++j) {
            if (cards[i + j].val != begVal + j||cards[i+j].count<=0) {
                isStraight = false;
                i=i+j;//从中断处重新找
                break;
            }
            minCount=min(minCount,cards[i+j].count);
        }
        if (isStraight) {
            ans += minCount;
            for (int j = 0; j < 5; ++j) cards[i + j].count-=minCount;
        }
        
       
        
    }
    
}

int main() {
    ll n;
    cin >> n;
    unordered_map<char, vector<Card>> hash;
    while (n--) {
        ll val, count;
        char style;
        cin >> val >> count >> style;
        hash[style].emplace_back(val, count, style);
    }

    vector<char> styles = {'S', 'H', 'D', 'C'};
    ll ans = 0;

    for (char s : styles) {
        auto& cards = hash[s];
        checkStraightFlush(cards, ans);
        
    }

    cout << ans << endl;
    return 0;
}

发表于 2025-08-21 00:26:30 回复(1)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+7;

// 贪心
void solve() {
    int n;
    cin >> n;
    vector<pair<int,int>>S,H,D,C;
    for(int i=1;i<=n;i++){
        int cnt,num;
        char ch;
        cin >> num >> cnt >> ch;
        if(ch == 'S') {
            S.push_back({num,cnt});
        }else if(ch=='H'){
            H.push_back({num,cnt});
        }else if(ch == 'D'){
            D.push_back({num,cnt});
        }else {
            C.push_back({num,cnt});
        }
    }
    sort(S.begin(),S.end());
    sort(H.begin(),H.end());
    sort(D.begin(),D.end());
    sort(C.begin(),C.end());
   
    int res=0;
    for(int i=0;i<S.size();i++){
     
        if(i+4<S.size()){
            bool ok=true;
            for(int j=i;j+1<=i+4;j++){
               if(S[j+1].first-S[j].first != 1){
                ok=false;
                break;
               }
            }
             
            if(ok){ // 是顺子
               int mi=S[i].second;
               for(int j=i;j<=i+4;j++){
                mi=min(mi,S[j].second);
               }
               res+=mi;
               for(int j=i;j<=i+4;j++){
                S[j].second-=mi;
               }
            }
 
        }
    }

        for(int i=0;i<H.size();i++){
        if(i+4<H.size()){
            bool ok=true;
            for(int j=i;j+1<=i+4;j++){
               if(H[j+1].first-H[j].first != 1){
                ok=false;
                break;
               }
            }
            if(ok){ // 是顺子
               int mi=H[i].second;
               for(int j=i;j<=i+4;j++){
                mi=min(mi,H[j].second);
               }
               res+=mi;
               for(int j=i;j<=i+4;j++){
                H[j].second-=mi;
               }
            }
        }
    }
        for(int i=0;i<D.size();i++){
        if(i+4<D.size()){
            bool ok=true;
            for(int j=i;j+1<=i+4;j++){
               if(D[j+1].first-D[j].first != 1){
                ok=false;
                break;
               }
            }
            if(ok){ // 是顺子
               int mi=D[i].second;
               for(int j=i;j<=i+4;j++){
                mi=min(mi,D[j].second);
               }
               res+=mi;
               for(int j=i;j<=i+4;j++){
                D[j].second-=mi;
               }
            }
        }
    }
        for(int i=0;i<C.size();i++){
        if(i+4<C.size()){
            bool ok=true;
            for(int j=i;j+1<=i+4;j++){
               if(C[j+1].first-C[j].first != 1){
                ok=false;
                break;
               }
            }
            if(ok){ // 是顺子
               int mi=C[i].second;
               for(int j=i;j<=i+4;j++){
                mi=min(mi,C[j].second);
               }
               res+=mi;
               for(int j=i;j<=i+4;j++){
                C[j].second-=mi;
               }
            }
        }
    }
    cout << res << '\n';
}

signed main() {
   solve();
    return 0;
}
发表于 2025-08-12 10:05:26 回复(0)