蓝桥杯真题

蓝桥杯真题

第十五届蓝桥杯A组

1.五子棋对弈

思路

  1. 棋盘表示

    • 使用二维数组 a[10][10] 来表示棋盘,尽管只需要 5x5,数组大小设置为 10x10 可能是为了未来扩展或防止越界。
  2. 全局变量

    • ans 用于记录满足条件的棋局数量。
  3. 深度优先搜索函数 dfs

    • 参数
      • n1:当前放置的白棋数量。
      • n2:当前放置的黑棋数量。
      • id:当前格子的序号(用于一维到二维的转换)。
      • c:当前放置的棋子的颜色(1 代表白棋,2 代表黑棋)。
  4. 边界条件检查

    • 如果白棋数量超过 13 或黑棋数量超过 12,或者 id 超过 25,立即返回,停止搜索。
  5. 棋子放置

    • 将当前格子的序号转换为二维坐标 (x, y),并将其设为当前棋子。
  6. 连成一线的检查

    • 行检查 :当当前行填满(y == 4)时,检查该行是否存在不同颜色的棋子。如果全是同色棋子,返回。
    • 列检查 :当当前列填满(x == 4)时,进行同样的检查。
    • 对角线检查:在特定的格子(id 为 20 和 24)时,检查两条对角线是否同色。
  7. 有效棋局的计数

    • 当所有棋子都放置完(id >= 24),增加有效棋局数量 ans
  8. 递归放置棋子

    • 尝试在下一个格子放置白棋和黑棋,递归调用 dfs
    • 撤销放置,恢复棋盘状态,以便进行下一次尝试。
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

// 棋盘表示
int a[10][10]; // 5×5 的棋盘表示
int ans = 0;   // 记录满足条件的棋局数量

// 深度优先搜索函数
void dfs(int n1, int n2, int id, int c) {
    // 如果白棋超过 13 个或黑棋超过 12 个,或者格子序号超出范围,停止搜索
    if (n1 >= 14 || n2 >= 13 || id >= 25) return;

    // 将一维的格子序号 id 转换为二维棋盘的坐标 (x, y)
    int x = id / 5, y = id % 5;
    a[x][y] = c; // 将当前格子放置对应棋子

    // 检查当前行是否连成一线
    if (y == 4) { // 行填满时才进行检查
        bool flag = 0;
        for (int i = 0; i <= 4; i++) {
            if (a[x][i] != a[x][0]) flag = 1; // 检查是否有不同颜色
        }
        if (flag == 0) return; // 如果全同色,返回
    }

    // 检查当前列是否连成一线
    if (x == 4) { // 列填满时才进行检查
        bool flag = 0;
        for (int i = 0; i <= 4; i++) {
            if (a[i][y] != a[0][y]) flag = 1; // 检查是否有不同颜色
        }
        if (flag == 0) return; // 如果全同色,返回
    }

    // 检查第一条对角线是否连成一线
    if (id == 20) { // 对角线填满时进行检查
        bool flag = 0;
        for (int i = 0; i <= 4; i++) {
            if (a[i][4-i] != a[0][4]) flag = 1; // 检查是否有不同颜色
        }
        if (flag == 0) return; // 如果全同色,返回
    }

    // 检查第二条对角线是否连成一线
    if (id == 24) { // 对角线填满时进行检查
        bool flag = 0;
        for (int i = 0; i <= 4; i++) {
            if (a[i][i] != a[0][0]) flag = 1; // 检查是否有不同颜色
        }
        if (flag == 0) return; // 如果全同色,返回
    }

    // 若已经枚举完最后一个棋子,说明是平局
    if (id >= 24) {
        ans++; // 增加符合条件的棋局数量
        return;
    }

    // 尝试将下一个格子放白棋
    dfs(n1 + 1, n2, id + 1, 1);
    // 撤销白棋
    a[(id + 1) / 5][(id + 1) % 5] = 0;

    // 尝试将下一个格子放黑棋
    dfs(n1, n2 + 1, id + 1, 2);
    // 撤销黑棋
    a[(id + 1) / 5][(id + 1) % 5] = 0;
}

int main() {
    // 从第一个格子开始,尝试放白棋
    dfs(1, 0, 0, 1);
    // 从第一个格子开始,尝试放黑棋
    dfs(0, 1, 0, 2);
    // 输出结果
    cout << ans;
    return 0;
}

2.训练士兵

使用后缀和从 rN(最大的训练次数)开始,向下遍历到 1。

对于每个 i,将 mp[i] 的值增加 mp[i + 1]。这意味着如果某训练次数为 i,则至少进行 i 次训练的士兵费用就应该包括进行 i + 1 次训练的费用(因为进行 i 次至少也会进行 i + 1 次的费用)。

这使得 mp[i] 最终包含了所有至少进行 i 次训练的士兵的费用总和

cpp 复制代码
#include <bits/stdc++.h> 
using namespace std;
using ll = long long;
const int N = 1e6 + 5, rN = 1e6;
ll n, s; // 士兵数量 n 和组团训练的成本 s
ll p, c, ans; // p 为每名士兵的单次训练成本,c 为士兵需要的训练次数,ans 用于记录最终总花费
map<ll, ll> mp; // 使用 map 存储不同训练次数对应的总训练成本

int main() {
    cin >> n >> s; 
    
   
    for(int i = 1; i <= n; i++) {
        cin >> p >> c; 
        mp[c] += p; // 将该士兵的训练成本累加到对应训练次数 c 的总费用中
    }
    
    // 计算后缀和,更新每种训练次数的总费用
    for(int i = rN; i >= 1; i--) {
        mp[i] += mp[i + 1]; // 从 rN 开始累加,将每个训练次数对应的费用更新为所有大于等于该次数的总费用
    }

    // 计算所有士兵的最小训练费用
    for(int i = 1; i <= rN; i++) {
        ans += min(mp[i], s); // 取每种训练次数的费用和组团训练费用 s 的最小值,累加到 ans 中
    }

    cout << ans; 
    return 0;
}
相关推荐
小龙报1 天前
《DevC++支持C++11等与其软件分辨率低的解决办法》
c语言·c++·windows·蓝桥杯·pat考试·学习方法·dvc++
Aldrich_322 天前
蓝桥杯嵌入式赛道—-软件篇(GPIO输出模式配置)
c语言·vscode·stm32·单片机·嵌入式硬件·蓝桥杯
hnjzsyjyj2 天前
洛谷 P12141:[蓝桥杯 2025 省 A] 红黑树
数据结构·蓝桥杯·二叉树
铭哥的编程日记2 天前
深入浅出蓝桥杯:算法基础概念与实战应用(二)基础算法(下)
算法·职场和发展·蓝桥杯
智者知已应修善业2 天前
【c语言蓝桥杯计算卡片题】2023-2-12
c语言·c++·经验分享·笔记·算法·蓝桥杯
_OP_CHEN2 天前
算法基础篇:(八)贪心算法之简单贪心:从直觉到逻辑的实战指南
c++·算法·贪心算法·蓝桥杯·算法竞赛·acm/icpc·简单贪心
遇印记3 天前
蓝桥java蜗牛
java·学习·蓝桥杯
_OP_CHEN4 天前
算法基础篇:(七)基础算法之二分算法 —— 从 “猜数字” 到 “解难题” 的高效思维
c++·算法·蓝桥杯·二分查找·acm·二分答案·二分算法
旭意5 天前
数据结构顺序表
数据结构·c++·蓝桥杯
落笔映浮华丶6 天前
蓝桥杯零基础到获奖-第4章 C++ 变量和常量
java·c++·蓝桥杯