题解 - 割韭菜(leek)

题目描述

韭菜是种生命力非常顽强的植物, 当播下种子在第 X 天就能进行第一次收割, 收割完成后重新生长, 再经过 Y 天后又能继续收割, 如果进行施肥则会缩短 W 天的成长时间, 如果已经长大了则不在继续缩短时间, 而且韭菜有个非常大的缺点, 不能过量施肥, 每个成长阶段只能施一次肥,当施肥过多可能会导致韭菜死亡。

小唐的爷爷拥有 1 亩韭菜地, 地里最多能种下 N 颗韭菜, 每次收割韭菜, 每颗韭菜能获得 1 斤, 爷爷的每日的工作安排顺序如下:

  • 能收割, 则进行收割
  • 需要施肥, 则进行施肥
  • 需要播种, 则进行播种。

因为爷爷很容易健忘, 可能会给韭菜过多的施肥, 过多施肥会导致韭菜地的韭菜死亡, 需要当天重新播种。

爷爷已经将韭菜播种完毕, 经过 T 天后, 爷爷能够收获多少斤韭菜呢?

输入格式

输入一行 N、 X 和 Y , 表示韭菜的数量, 韭菜的初次生长日期, 以及再次生长日期

输入一行 T、 M 和 W , 表示天数, 施肥的次数以及缩短的天数

接下来 M 行, 输入 Ai, 表示在第几天施肥。

输出格式

爷爷一共收获多少斤的韭菜。

样例

样例输入

8 4 2

10 4 1

1

2

6

9

样例输出

32

样例解释

第一天: 施肥

第二天: 施肥, 该阶段多次施肥, 重新播种

第六天: 收割, 施肥

第七天: 收割

第九天: 收割, 施肥

第十天: 收割

数据范围

在这里插入图片描述

思路分析

注意:此题题目存在歧义(没有明确说明某一天是否可以重复施肥,即同一天是否最多只能施肥一次)。

按理说应该考虑重复施肥,但官方给的标程并没有考虑,并且存在重复施肥的测试数据点。

不过不管是按照哪种题意进行理解,该题解均可胜任,只存在某一行代码的区别,首先先介绍我的理解,即“可以重复施肥”。

由于T <= 1e6,故我们可以枚举天数。

对于每天,我们可以分别处理 收割、施肥、播种 。

首先处理收割

用tmp表示离收割还有多少天,则每天的开始,tmp需要减1。且若tmp <= 0,则说明可以收割,进行收割即可。

tmp--;
if(tmp <= 0){
    tmp = y; // tmp初始化为y(因为已经进行了一次收割)
    // cnt表示收割的总次数
    cnt++; // 收割的次数+1
    // flag表示一个生长周期内是否进行过施肥
    flag = false; // 新的生长周期开始,flag初始化为false
} 

然后处理施肥和播种

用st数组表示当天是否进行施肥。

if(st[i] == 1){ // 如果当天进行施肥
    if(!flag){ // 若当前生长周期内没有施过肥
        tmp -= w; // 天数减小w
        flag = true; // 标记当前生长周期已经施过肥
    }else{
        // 若当前生长周期内已经施过肥了,则种子会死亡,会重新播种
        tmp = x; 
        flag = false;
    }
}else if(st[i] > 1){
    // 若当天不止施肥一次,则种子肯定死亡,会重新播种
    tmp = x;
    flag = false;
}

时间复杂度O(T)。

接下来说明按照官方的理解(同一天最多只能施肥一次):

ps:由于官方的数据存在“重复施肥”的情况,所以按照我的理解会WA,进行如下修改即可AC官方数据(官方数据如果未修正的话)

只需要把读入数据时统计st[j]的代码改成st[j] = 1即可

    cin >> n >> x >> y >> t >> m >> w;
    for(int i = 0,j;i < m;i++){
        cin >> j;
        // st[j]++;
        st[j] = 1; // 按照官方的理解进行修改
    }

代码

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1e6 + 10;

int n,x,y;
int t,m,w;
int st[N];
int cnt;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);

    cin >> n >> x >> y >> t >> m >> w;
    for(int i = 0,j;i < m;i++){
        cin >> j;
        st[j]++; // 我的理解
        // st[j] = 1; // 官方的理解
    }

    int tmp = x;
    bool flag = false;
    for(int i = 1;i <= t;i++){
        // 收割
        tmp--;
        if(tmp <= 0){
            cnt++;
            tmp = y;
            flag = false;
        } 

        // 施肥
        if(st[i] == 1){
            if(!flag){
                tmp -= w;
                flag = true;
            }else{
                // 播种
                tmp = x;
                flag = false;
            }
        }else if(st[i] > 1){
            // 播种
            tmp = x;
            flag = false;
        }
    }

    cout << (LL)cnt * n;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值