1 条题解

  • 0
    @ 2025-7-15 19:06:59

    方法思路

    1. 这道题要求我们从牌堆中选取5张牌构成同花顺,每个同花顺得1分,问最多能得多少分。
    2. 首先,按照花色将牌分组,然后在每个花色内寻找连续的5张牌。
    3. 对于每个花色,我们需要:
      • 将该花色的所有牌按数值排序
      • 使用滑动窗口找出所有可能的连续5张牌
      • 对于每个找到的同花顺,计算能组成的数量(取决于5张牌中数量最少的那种)
    4. 关键点:当找到一个同花顺后,需要将使用过的牌从牌堆中减去,因为每张牌只能使用一次

    代码实现

    Java
    import java.util.*;
    import java.io.*;
    
    public class Main {
        static class Poker {
            int digital;
            int count;
            
            public Poker(int digital, int count) {
                this.digital = digital;
                this.count = count;
            }
        }
        
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int n = Integer.parseInt(br.readLine());
            
            // 使用TreeMap按数值排序
            Map<Character, TreeMap<Integer, Integer>> mp = new HashMap<>();
            mp.put('S', new TreeMap<>());
            mp.put('H', new TreeMap<>());
            mp.put('D', new TreeMap<>());
            mp.put('C', new TreeMap<>());
            
            StringTokenizer st;
            for (int i = 0; i < n; i++) {
                st = new StringTokenizer(br.readLine());
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());
                char ch = st.nextToken().charAt(0);
                
                mp.get(ch).put(x, y);
            }
            
            long res = 0;
            
            // 处理每种花色
            for (Map.Entry<Character, TreeMap<Integer, Integer>> entry : mp.entrySet()) {
                TreeMap<Integer, Integer> cards = entry.getValue();
                
                // 如果牌数小于5,无法组成同花顺
                if (cards.size() < 5) continue;
                
                // 将牌值转换为列表,以便更快地访问
                List<Integer> values = new ArrayList<>(cards.keySet());
                
                for (int i = 0; i <= values.size() - 5; i++) {
                    // 检查是否连续
                    boolean isConsecutive = true;
                    for (int j = 0; j < 4; j++) {
                        if (values.get(i + j + 1) != values.get(i + j) + 1) {
                            isConsecutive = false;
                            // 优化:直接跳到不连续的位置
                            i = i + j;
                            break;
                        }
                    }
                    
                    if (isConsecutive) {
                        // 找到最小牌数
                        int minCount = Integer.MAX_VALUE;
                        for (int j = 0; j < 5; j++) {
                            minCount = Math.min(minCount, cards.get(values.get(i + j)));
                        }
                        
                        // 更新结果
                        res += minCount;
                        
                        // 更新剩余牌数
                        for (int j = 0; j < 5; j++) {
                            int value = values.get(i + j);
                            cards.put(value, cards.get(value) - minCount);
                        }
                    }
                }
            }
            
            System.out.println(res);
        }
    }
    
    
    Python
    def max_score(cards):
        # 按花色分组
        suits = {'S': [], 'H': [], 'D': [], 'C': []}
        
        for value, count, suit in cards:
            suits[suit].append((value, count))
        
        total_score = 0
        
        # 处理每种花色
        for suit, cards_list in suits.items():
            # 如果牌数小于5,无法组成同花顺
            if len(cards_list) < 5:
                continue
            
            # 将该花色的所有牌按数值排序
            cards_list.sort()
            
            i = 0
            while i <= len(cards_list) - 5:
                dig = cards_list[i][0]
                mark = cards_list[i][1]
                flag = True
                j = i + 1
                
                # 检查是否能形成连续5张牌
                for j in range(i + 1, i + 5):
                    if j < len(cards_list) and cards_list[j][0] == dig + 1:
                        mark = min(mark, cards_list[j][1])  # 求最小同花顺数量
                        dig = cards_list[j][0]
                    else:
                        flag = False
                        break
                
                # 如果找到同花顺
                if flag:
                    total_score += mark
                    # 减去已使用的牌
                    for j in range(i + 1, i + 5):
                        cards_list[j] = (cards_list[j][0], cards_list[j][1] - mark)
                else:
                    # 优化:直接跳到不连续的位置
                    i = j - 1
                
                i += 1
        
        return total_score
    
    # 读取输入
    n = int(input())
    cards = []
    for _ in range(n):
        value, count, suit = input().split()
        cards.append((int(value), int(count), suit))
    
    # 计算并输出结果
    print(max_score(cards))
    
    
    C++
    #include <iostream>
    #include <vector>
    #include <unordered_map>
    #include <algorithm>
    using namespace std;
    
    struct Poker {
        int digital;
        int count;
        Poker() {}
        Poker(int x, int y) : digital(x), count(y) {}
    };
    
    int main() {
        int n;
        cin >> n;
        
        unordered_map<char, vector<Poker>> mp;
        
        for (int i = 0; i < n; i++) {
            int x, y;
            char ch;
            cin >> x >> y >> ch;
            
            mp[ch].push_back(Poker(x, y));
        }
        
        long long res = 0;
        
        // 处理每种花色
        for (auto& pokarray : mp) {
            // 如果牌数小于5,无法组成同花顺
            if (pokarray.second.size() < 5) continue;
            
            // 将该花色的所有牌按数值排序
            sort(pokarray.second.begin(), pokarray.second.end(), 
                 [](const Poker& a, const Poker& b) { return a.digital < b.digital; });
            
            int i = 0;
            while (i <= pokarray.second.size() - 5) {
                int dig = pokarray.second[i].digital;
                int mark = pokarray.second[i].count;
                bool flag = true;
                int j = i + 1;
                
                // 检查是否能形成连续5张牌
                for (; j < i + 5; j++) {
                    if (pokarray.second[j].digital == dig + 1) {
                        mark = min(mark, pokarray.second[j].count);  // 求最小同花顺数量
                        dig = pokarray.second[j].digital;
                    } else {
                        flag = false;
                        break;
                    }
                }
                
                // 如果找到同花顺
                if (flag) {
                    res += mark;
                    // 减去已使用的牌
                    for (int j = i + 1; j < i + 5; j++) {
                        pokarray.second[j].count -= mark;
                    }
                } else {
                    // 优化:直接跳到不连续的位置
                    i = j - 1;
                }
                
                i++;
            }
        }
        
        cout << res << endl;
        return 0;
    }
    
    
    • 1

    信息

    ID
    89
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    8
    已通过
    1
    上传者