学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考青铜组别比赛学习过程中的题目,记录每一个瞬间。
附上汇总贴:USACO历年青铜组真题解析 | 汇总-CSDN博客
【题目描述】
Farmer John 有 N(1≤N≤10^5) 头奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。她们沿水平方向排成一行,奶牛们占据的位置编号为 1⋯N。
由于奶牛们都饿了,FJ 决定在 1⋯N 中的某些位置上种植草地。更赛牛和荷斯坦牛喜欢不同类型的草,所以如果 Farmer John 决定在某个位置种草,他必须选择种植更赛牛喜欢的草或荷斯坦牛喜欢的草——他不能在同一个位置同时种两种草。种植的每一片草地都可以喂饱数量不限的相应品种的奶牛。
每头奶牛愿意移动至多 K(0≤K≤N−1) 个位置以前往一个草地。求出喂饱所有奶牛所需种植的最小草地数量。此外,输出一种使用最小草地数量喂饱所有奶牛的种植方案。任何满足上述条件的方案均视为正确。
【输入】
每个测试用例包含 T 个子测试用例,为一种奶牛的排列。输入的第一行包含 T(1≤T≤10)。以下是 T 个子测试用例。
每个子测试用例的第一行包含 N 和 K。第二行包含一个长度为 N 的字符串,其中第 i 个字符表示第 i 头奶牛的品种(G 表示更赛牛,H 表示荷斯坦牛)。
【输出】
对于 T 个子测试用例中的每一个,输出两行。第一行输出喂饱所有奶牛所需的最小草地数量。第二行输出一个长度为 N 的字符串,表示一种使用最小草地数量喂饱所有奶牛的种植方案。第 i 个字符表示第 i 个位置,若不种草则为 .,若种植喂饱更赛牛的草则为 G,若种植喂饱荷斯坦牛的草则为 H。任何合法的方案均可通过。
【输入样例】
6
5 0
GHHGG
5 1
GHHGG
5 2
GHHGG
5 3
GHHGG
5 4
GHHGG
2 1
GH
【输出样例】
5
GHHGG
3
.GH.G
2
..GH.
2
...GH
2
...HG
2
HG
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int t, n, k;
char cow[100005]={0}, ans[100005]; // 定义cow数组存放奶牛品种,ans数组存放种植的草
int main()
{
cin >> t; // 输入t
for (int i=1; i<=t; i++) { // for循环遍历t个测试用例
int cnt = 0; // 初始化最小草地数量,初始为0
memset(ans, '.', sizeof(ans)); //每次循环初始化草地数组
cin >> n >> k; // 输入n和k
for (int j=1; j<=n; j++) { // 遍历n个字符
cin >> cow[j]; // 记录在cow数组中
}
// 先遍历一遍,种植G草
int mark=1; // 定义起始坐标
while (mark<=n) { // 只要坐标没有越界
if (cow[mark]=='G') { // 如果该坐标位置为G牛
if ((mark+k)<n) { // 如果mark+k没有越边界
ans[mark+k] = 'G'; // 则在mark+k的位置种植G草
mark = mark+2*k+1; // 并把位置修改为mark+2k+1,因为mark到mark+2k之间所有的牛都可以吃mark+k位置的草
} else { // 如果坐标越界
ans[n] = 'G'; // 则最后一个位置种植G草
break; // 退出循环
}
} else mark++; // 否则mark自增,直到找到位置为G牛的坐标
}
// 再遍历一遍,种植H草
int mark2=1; // 定义起始坐标
while (mark2<=n) { // 只要坐标没有越界
if (cow[mark2]=='H') { // 如果该坐标位置为H牛
if ((mark2+k)<n) { // 如果mark+k小于n
ans[mark2+k] = 'H'; // 则在mark+k的位置种植H草
mark2 = mark2+2*k+1; // 并把位置修改为mark+2k+1,因为mark到mark+2k之间所有的牛都可以吃mark+k位置的草
} else { // 如果mark+k>=n
if (ans[n]=='G') { // 判断n这个位置是否有G草
ans[n-1] = 'H'; // 如果有,则在n-1的位置种上H草
break; // 退出循环
} else { // 如果没有
ans[n] = 'H'; // 则种上H草
break; // 退出循环
}
}
} else mark2++; // 否则mark自增,直到找到位置为H牛的坐标
}
for (int i=1; i<=n; i++) { // for循环遍历n个位置
if (ans[i]!='.') cnt++; // 对于种草的位置,cnt自增
}
cout << cnt << endl; // 输出草地数量
for (int i=1; i<=n; i++) { // 再for循环遍历n个位置
cout << ans[i]; // 输出种植的草(有些题有多个解,但不影响结果判断)
}
cout << endl;
}
return 0;
}
【运行结果】
6
5 0
GHHGG
5
GHHGG
5 1
GHHGG
3
.GH.G
5 2
GHHGG
2
..GH.
5 3
GHHGG
2
...GH
5 4
GHHGG
2
...HG
2 1
GH
2
HG