P8898题解

思路


这是一道贪心题。我们先考虑更赛牛。


- 首先,一个草如果要供最多牛食用,它就要尽可能远离最远的牛,这样才能保证另一端更多的牛能吃到。这样一格草就能最多满足 $2 \times k + 1$ 只同一种牛的食用需求。

- 但是,如果第 $i$ 只牛已经靠近另一端,$i + k$ 已经超出了草地 $a$ 的距离,我们就将最后一格草放在草地的最末尾。这样就能放置最少的草地就能满足所有的更赛牛。

- 荷斯坦牛的方法显然也类似,要尽可能满足最多的牛,它要尽量放置在 $i + k$ 的位置,这保证和之前不会重复。因为 $i$ 位置的牛是唯一的,所以 $i + k$ 位置肯定没有被占用。

- 我们同时也要考虑荷斯坦牛最后一格草超出边境的问题。因为边界已经被更赛牛占用,我们就从 $a$$1$ 依次遍历找到空的格子放上就行了。一定要遍历到 $1$ 或者 $i - 1$,如果遍历到 $i$ 过不了样例的最后一小点($a = i$)。

- 最后记得统计喂饱所有奶牛所需的最小草地数量,循环一遍即可。

 代码


AC记录

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<map>
#include<algorithm>

using namespace std;

// 快读
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    while (ch < '0' or ch > '9'){if (ch == '-') f = -1;ch = getchar();}
    while (ch >= '0' and ch<='9'){x = x * 10 + ch - 48;ch = getchar();}
    return x * f;
}
int main() {
    int t = read();
    while(t--) {
        //定义变量及输入
        int a = read(),k = read(),ans = 0;
        char c[100005],d[100005];
        for(int i = 1;i <= a;i++) cin>>c[i],d[i] = '.';
        //更赛牛
        for(int i = 1;i <= a;i++) {
            if(c[i] == 'G') {
                //未超出边界时
                if(i + k <= a) {
                    d[i + k] = 'G';
                }
                //超出边界时
                else {
                    d[a] = 'G';
                }
                //满足了牛的需求后记得加跳过已经满足的部分。
                i += 2 * k;    
            }
        }
        //荷斯坦牛
        for(int i = 1;i <= a;i++) {
            if(c[i] == 'H') {
                未超出边界时
                if(i + k < a) {
                    d[i + k] = 'H';
                }
                //超出边界时
                else {
                    for(int j = a;j >=     1;j--) {
                        if(d[j] == '.'){
                            d[j] = 'H';
                            break;
                        }
                    }
                }
                i += 2 * k;    
            }
        }
        //统计ans和输出
        for(int i = 1;i <= a;i++) if(d[i] != '.') ans++;
        printf("%d\n",ans);
        for(int i = 1;i <= a;i++) cout<<d[i];
        printf("\n");
    } 
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值