1 条题解

  • 0
    @ 2025-4-10 0:04:19

    题目分析

    Yahtzee游戏涉及13轮掷骰子,每轮掷5个骰子。玩家需要在13个不同的类别中选择一个来记录分数,每个类别只能使用一次。最终分数是所有类别分数的总和,如果前六个类别的总和达到或超过63分,则额外获得35分的奖励。

    方法思路

    1. 输入处理:读取13轮掷骰子的结果,每轮5个骰子的值。

    2. 计算每个类别的分数:

      • ones到sixes:计算对应数字的总和。

      • chance:所有骰子的总和。

      • three of a kind和four of a kind:检查是否有至少三个或四个相同的骰子,满足则计算总和。

      • five of a kind:检查是否所有骰子相同,满足则得50分。

      • short straight和long straight:检查是否有四个或五个连续的骰子,满足则得25或35分。

      • full house:检查是否有三个相同和另外两个相同的骰子,满足则得40分。

    3. 计算总分:将所有类别分数相加,并检查前六个类别的总和是否达到63分以确定是否获得35分的奖励。

    4. 输出结果:按顺序输出13个类别的分数、奖励分数和总分。

    解决代码

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <numeric>
    using namespace std;
    
    vector<int> calculate_scores(const vector<vector<int>>& rounds) {
        vector<int> scores(13, 0);
        vector<int> counts(7, 0);
        int sum = 0;
        for (int i = 0; i < 13; ++i) {
            fill(counts.begin(), counts.end(), 0);
            sum = 0;
            for (int die : rounds[i]) {
                counts[die]++;
                sum += die;
            }
            // ones to sixes
            for (int j = 1; j <= 6; ++j) {
                if (counts[j] > 0) {
                    scores[j-1] = max(scores[j-1], j * counts[j]);
                }
            }
            // chance
            scores[6] = max(scores[6], sum);
            // three of a kind
            bool three = false;
            for (int j = 1; j <= 6; ++j) {
                if (counts[j] >= 3) {
                    three = true;
                    break;
                }
            }
            if (three) {
                scores[7] = max(scores[7], sum);
            }
            // four of a kind
            bool four = false;
            for (int j = 1; j <= 6; ++j) {
                if (counts[j] >= 4) {
                    four = true;
                    break;
                }
            }
            if (four) {
                scores[8] = max(scores[8], sum);
            }
            // five of a kind
            bool five = false;
            for (int j = 1; j <= 6; ++j) {
                if (counts[j] >= 5) {
                    five = true;
                    break;
                }
            }
            if (five) {
                scores[9] = max(scores[9], 50);
            }
            // short straight
            bool short_straight = false;
            for (int j = 1; j <= 3; ++j) {
                if (counts[j] >= 1 && counts[j+1] >= 1 && counts[j+2] >= 1 && counts[j+3] >= 1) {
                    short_straight = true;
                    break;
                }
            }
            if (short_straight) {
                scores[10] = max(scores[10], 25);
            }
            // long straight
            bool long_straight = false;
            if ((counts[1] >= 1 && counts[2] >= 1 && counts[3] >= 1 && counts[4] >= 1 && counts[5] >= 1) ||
                (counts[2] >= 1 && counts[3] >= 1 && counts[4] >= 1 && counts[5] >= 1 && counts[6] >= 1)) {
                long_straight = true;
            }
            if (long_straight) {
                scores[11] = max(scores[11], 35);
            }
            // full house
            bool full_house = false;
            bool three_found = false;
            bool two_found = false;
            for (int j = 1; j <= 6; ++j) {
                if (counts[j] == 3) {
                    three_found = true;
                } else if (counts[j] == 2) {
                    two_found = true;
                }
            }
            if (three_found && two_found) {
                full_house = true;
            }
            if (full_house) {
                scores[12] = max(scores[12], 40);
            }
        }
        return scores;
    }
    
    int main() {
        vector<vector<int>> rounds;
        for (int i = 0; i < 13; ++i) {
            vector<int> round(5);
            for (int j = 0; j < 5; ++j) {
                cin >> round[j];
            }
            rounds.push_back(round);
        }
        vector<int> scores = calculate_scores(rounds);
        int upper_sum = accumulate(scores.begin(), scores.begin() + 6, 0);
        int bonus = (upper_sum >= 63) ? 35 : 0;
        int total = accumulate(scores.begin(), scores.end(), 0) + bonus;
        for (int score : scores) {
            cout << score << " ";
        }
        cout << bonus << " " << total << endl;
        return 0;
    }
    

    代码解释

    1. calculate_scores函数:计算每轮掷骰子后各个类别的分数。
    2. main函数:读取输入数据,调用calculate_scores计算分数,计算总分和奖励分数,并输出结果。
    3. generate_round和generate_game函数:生成随机的掷骰子结果,用于测试。
    4. 输入输出数据生成程序:生成随机的游戏数据,用于测试和验证代码的正确性。
    • 1

    信息

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