题解:B4180 [厦门小学生 C++ 2024] 乌龟对对碰

· · 题解

题目跳转站:

B4180 [厦门小学生 C++ 2024] 乌龟对对碰

代码解析:

纯模拟题!!!

函数:

p1 函数: 判断是否满足条件 1,通过统计九宫格中每种颜色乌龟数量,找出成对的乌龟并移除,返回拿走的乌龟对数(即赠送盲盒数)。

代码:

int p1() {
    // 记录生成的新字符数量
    int n = 0;
    // 初始化计数数组
    memset(c, 0, sizeof(c));
    // 统计九宫格中每个数字出现的次数
    for (int x = 1; x <= 3; x++) {
        for (int y = 1; y <= 3; y++) {
            if (g[x][y] != -1) {
                c[g[x][y]]++;
            }
        }
    }
    // 遍历每个数字
    for (int x = 0; x < 10; x++) {
        if (c[x] < 2) continue;
        // 计算该数字可组成的对数
        int t = c[x] / 2 * 2;
        // 累加生成的新字符数量
        n += c[x] / 2;
        // 更新该数字剩余的数量
        c[x] %= 2;
        // 从九宫格中移除组成对的数字
        for (int y = 1; y <= 3; y++) {
            for (int z = 1; z <= 3; z++) {
                if (g[y][z] == x) {
                    g[y][z] = -1;
                    if (--t == 0) break;
                }
            }
            if (t < 1) break;
        }
    }
    return n;
}

p2 函数: 判断是否满足条件 2,在满足条件 1 的基础上,检查按条件 1 操作后 9 宫格是否为空,若为空返回赠送盲盒数 8,否则返回 0。

代码:

// 处理九宫格全空的特殊情况的函数
int p2() {
    // 标记九宫格是否全空
    bool e = true;
    for (int x = 1; x <= 3; x++) {
        if (g[x][1] != -1 || g[x][2] != -1 || g[x][3] != -1) {
            e = false;
        }
    }
    // 如果满足特定条件且九宫格全空
    if (f && e) {
        return 8;
    }
    return 0;
}

p3 函数: 判断是否满足条件 3,检查 9 宫格是否全满且乌龟颜色各不相同,若满足返回赠送盲盒数 10,否则返回 0。

代码:

// 处理九宫格无重复数字的特殊情况的函数
int p3() {
    // 标记九宫格是否有空位
    bool e = false;
    for (int x = 1; x <= 3; x++) {
        for (int y = 1; y <= 3; y++) {
            if (g[x][y] == -1) {
                e = true;
            }
        }
    }
    // 如果有空位,直接返回 0
    if (e) return 0;
    // 重新初始化计数数组
    memset(c, 0, sizeof(c));
    // 统计九宫格中每个数字出现的次数
    for (int x = 1; x <= 3; x++) {
        for (int y = 1; y <= 3; y++) {
            if (g[x][y] != -1) {
                c[g[x][y]]++;
            }
        }
    }
    // 标记九宫格中的数字是否都唯一
    bool u = true;
    for (int x = 0; x < 10; x++) {
        if (c[x] > 1) {
            u = false;
            break;
        }
    }
    // 如果数字都唯一
    if (u) {
        // 清空九宫格
        for (int x = 1; x <= 3; x++) {
            for (int y = 1; y <= 3; y++) {
                g[x][y] = -1;
            }
        }
        return 10;
    }
    return 0;
}

主流程: 读取盲盒序列和购买的盲盒数量,将购买的盲盒存入 w 。进入循环,不断将未打开的盲盒放入 9 宫格,检查三个条件。若满足条件,根据条件获得赠送盲盒并更新 w 和最终获得乌龟总数 a 。若某一轮没有获得赠送盲盒,说明游戏结束,计算并输出最终获得的乌龟总数(购买的盲盒数量 b 加上赠送的乌龟数量 a )。

代码:

int main() {
    // 输入字符串
    cin >> s;
    // 输入初始购买的字符数量
    scanf("%d", &b);
    // 初始购买字符添加到可用字符中
    for (int x = 0; x < b; x++) {
        w += s[i++];
    }
    while (1) {
        // 标记本轮是否有变化
        bool ch = false;
        // 可用字符的索引
        int j = -1;
        // 可用字符的长度
        int l = w.size();
        // 填充九宫格
        for (int x = 1; x <= 3; x++) {
            for (int y = 1; y <= 3; y++) {
                if (g[x][y] == -1 && j + 1 < l) {
                    g[x][y] = w[++j] - '0';
                }
            }
        }
        // 移除已使用的可用字符
        w.erase(0, j + 1);
        // 调用 p1 函数处理相同数字对
        int r = p1();
        if (r) {
            f = true;
            ch = true;
            // 生成新的可用字符
            for (int x = 1; x <= r; x++) {
                w += s[i++];
            }
            // 累加结果
            a += r;
        }
        // 调用 p2 函数处理全空情况
        r = p2();
        if (r) {
            ch = true;
            // 生成新的可用字符
            for (int x = 1; x <= r; x++) {
                w += s[i++];
            }
            // 累加结果
            a += r;
        }
        // 调用 p3 函数处理无重复数字情况
        r = p3();
        if (r) {
            ch = true;
            // 生成新的可用字符
            for (int x = 1; x <= r; x++) {
                w += s[i++];
            }
            // 累加结果
            a += r;
        }
        // 如果本轮没有变化,退出循环
        if (!ch) break;
    }
    // 输出最终结果
    printf("%d", a + b);
    return 0;
}

最终代码:

#include <bits/stdc++.h>
using namespace std;

// 存储输入的字符串
string s;
// 存储当前可用的字符
string w;
// 初始购买的字符数量
int b;
// 当前处理到输入字符串的索引
int i;
// 记录每个数字出现的次数
int c[11];
// 最终结果
int a;
// 3x3 的九宫格数组,初始值为 -1 表示空位
int g[4][4] = {
    {-1, -1, -1, -1},
    {-1, -1, -1, -1},
    {-1, -1, -1, -1},
    {-1, -1, -1, -1}
};
// 标记是否满足特定条件
bool f;

// 处理九宫格中相同数字对的函数
int p1() {
    // 记录生成的新字符数量
    int n = 0;
    // 初始化计数数组
    memset(c, 0, sizeof(c));
    // 统计九宫格中每个数字出现的次数
    for (int x = 1; x <= 3; x++) {
        for (int y = 1; y <= 3; y++) {
            if (g[x][y] != -1) {
                c[g[x][y]]++;
            }
        }
    }
    // 遍历每个数字
    for (int x = 0; x < 10; x++) {
        if (c[x] < 2) continue;
        // 计算该数字可组成的对数
        int t = c[x] / 2 * 2;
        // 累加生成的新字符数量
        n += c[x] / 2;
        // 更新该数字剩余的数量
        c[x] %= 2;
        // 从九宫格中移除组成对的数字
        for (int y = 1; y <= 3; y++) {
            for (int z = 1; z <= 3; z++) {
                if (g[y][z] == x) {
                    g[y][z] = -1;
                    if (--t == 0) break;
                }
            }
            if (t < 1) break;
        }
    }
    return n;
}

// 处理九宫格全空的特殊情况的函数
int p2() {
    // 标记九宫格是否全空
    bool e = true;
    for (int x = 1; x <= 3; x++) {
        if (g[x][1] != -1 || g[x][2] != -1 || g[x][3] != -1) {
            e = false;
        }
    }
    // 如果满足特定条件且九宫格全空
    if (f && e) {
        return 8;
    }
    return 0;
}

// 处理九宫格无重复数字的特殊情况的函数
int p3() {
    // 标记九宫格是否有空位
    bool e = false;
    for (int x = 1; x <= 3; x++) {
        for (int y = 1; y <= 3; y++) {
            if (g[x][y] == -1) {
                e = true;
            }
        }
    }
    // 如果有空位,直接返回 0
    if (e) return 0;
    // 重新初始化计数数组
    memset(c, 0, sizeof(c));
    // 统计九宫格中每个数字出现的次数
    for (int x = 1; x <= 3; x++) {
        for (int y = 1; y <= 3; y++) {
            if (g[x][y] != -1) {
                c[g[x][y]]++;
            }
        }
    }
    // 标记九宫格中的数字是否都唯一
    bool u = true;
    for (int x = 0; x < 10; x++) {
        if (c[x] > 1) {
            u = false;
            break;
        }
    }
    // 如果数字都唯一
    if (u) {
        // 清空九宫格
        for (int x = 1; x <= 3; x++) {
            for (int y = 1; y <= 3; y++) {
                g[x][y] = -1;
            }
        }
        return 10;
    }
    return 0;
}

int main() {
    // 输入字符串
    cin >> s;
    // 输入初始购买的字符数量
    scanf("%d", &b);
    // 初始购买字符添加到可用字符中
    for (int x = 0; x < b; x++) {
        w += s[i++];
    }
    while (1) {
        // 标记本轮是否有变化
        bool ch = false;
        // 可用字符的索引
        int j = -1;
        // 可用字符的长度
        int l = w.size();
        // 填充九宫格
        for (int x = 1; x <= 3; x++) {
            for (int y = 1; y <= 3; y++) {
                if (g[x][y] == -1 && j + 1 < l) {
                    g[x][y] = w[++j] - '0';
                }
            }
        }
        // 移除已使用的可用字符
        w.erase(0, j + 1);
        // 调用 p1 函数处理相同数字对
        int r = p1();
        if (r) {
            f = true;
            ch = true;
            // 生成新的可用字符
            for (int x = 1; x <= r; x++) {
                w += s[i++];
            }
            // 累加结果
            a += r;
        }
        // 调用 p2 函数处理全空情况
        r = p2();
        if (r) {
            ch = true;
            // 生成新的可用字符
            for (int x = 1; x <= r; x++) {
                w += s[i++];
            }
            // 累加结果
            a += r;
        }
        // 调用 p3 函数处理无重复数字情况
        r = p3();
        if (r) {
            ch = true;
            // 生成新的可用字符
            for (int x = 1; x <= r; x++) {
                w += s[i++];
            }
            // 累加结果
            a += r;
        }
        // 如果本轮没有变化,退出循环
        if (!ch) break;
    }
    // 输出最终结果
    printf("%d", a + b);
    return 0;
}