T1. 拼点游戏
C 和 S 两位同学一起玩拼点游戏。有一堆白色卡牌和一堆蓝色卡牌,每张卡牌上写了一个整数点数。C 随机抽取 n n n 张白色卡牌,S 随机抽取 n n n 张蓝色卡牌,他们进行 n n n 回合拼点,每次两人各出一张卡牌,点数大者获得三颗巧克力,小者获得一颗巧克力,如果点数相同,每人各得二颗巧克力,使用过的卡牌不得重复使用。已知 C 和 S 取到的卡牌点数,请编程计算 S 最多和最少能得到多少颗巧克力。
时间限制:1 s
内存限制:64 MB
- 输入
输入包含多组测试数据。每组测试数据的第一行是一个整数 n ( 1 ≤ n ≤ 2000 ) n\ (1\le n\le 2000) n (1≤n≤2000),接下来一行是 n n n 个整数,表示 C 抽到的白色卡牌的点数,下一行也是 n n n 个整数,表示 S 抽到的蓝色卡牌的点数。输入的最后以一个 0 0 0 表示结束。 - 输出
对每组数据,输出一行,内容是两个整数用空格格开,分别表示 S 最多和最少可获得的巧克力数。 - 样例输入
3 92 83 71 95 87 74 2 20 20 20 20 2 20 19 22 18 0
- 样例输出
9 5 4 4 4 4
思路分析
此题考查动态规划与贪心,与 2023 年 12 月四级第三题【田忌赛马】基本一致,具体解析可以参考 2023 年 12 月青少年软编等考 C 语言四级真题解析中的 T3。
此处仅给出贪心算法的示例代码。由于需要计算最高和最低得分,于是可以将拼点过程封装成函数,计算 a [ ] a[] a[] 最高可以赢得多少分,胜利得 3 3 3 分,失败得 1 1 1 分。计算最低得分时将两个数组交换位置,相当于计算 b [ ] b[] b[] 最高可以赢得多少分,但是我们最终需要统计 a [ ] a[] a[] 的最低得分,由于 b [ ] b[] b[] 的胜利就是 a [ ] a[] a[] 的失败,于是将胜利得分修改为 1 1 1,失败得分修改为 3 3 3 即可。
/*
* Name: T1.cpp
* Problem: 拼点游戏
* Author: Teacher Gao.
* Date&Time: 2025/07/17 15:11
*/
#include <bits/stdc++.h>
using namespace std;
int n, a[2005] = {
0}, b[2005] = {
0};
// 计算 a[] 最高赢得多少分,胜利得 x 分,失败得 y 分
int compare(int a[], int b[], int x, int y) {
int La = 1, Ra = n, Lb = 1, Rb = n, tot = 0;
for (int i = 1; i <= n; ++i) {
if (a[La] > b[Lb]) ++La, ++Lb, tot += x;
else if (a[La] < b[Lb]) --Ra, ++Lb, tot += y;
else {
if (a[Ra] > b[Rb]) --Ra, --Rb, tot += x;
else if (a[Ra] < b[Lb]) --Ra, ++Lb, tot += y;
else ++La, ++Lb, tot += 2; // 平局,这里与田忌赛马不一样
}
}
return tot;
}
int main()
{
while (scanf("%d", &n) && n) {
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
sort(a + 1, a + n + 1, greater<int>());
sort(b + 1, b + n + 1, greater<int>());
printf("%d %d\n", compare(b, a, 3, 1), compare(a, b, 1, 3));
}
return 0;
}
T2. 数字变换
给定一个包含 5 5 5 个数字( 0 ∼ 9 0\sim 9 0∼9)的字符串,例如 "02943"
,请将 "12345"
变换到它。你可以采取