USACO历年青铜组真题解析 | 2022年12月Feeding the Cows

学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考青铜组别比赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:USACO历年青铜组真题解析 | 汇总-CSDN博客


【题目描述】

Farmer John 有 N(1≤N≤10^5) 头奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。她们沿水平方向排成一行,奶牛们占据的位置编号为 1⋯N

由于奶牛们都饿了,FJ 决定在 1⋯N 中的某些位置上种植草地。更赛牛和荷斯坦牛喜欢不同类型的草,所以如果 Farmer John 决定在某个位置种草,他必须选择种植更赛牛喜欢的草或荷斯坦牛喜欢的草——他不能在同一个位置同时种两种草。种植的每一片草地都可以喂饱数量不限的相应品种的奶牛。

每头奶牛愿意移动至多 K(0≤KN−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
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值