牛客 NC24724 Feb S]Chocolate Eating 解题报告

原题链接:

登录—专业IT笔试面试备考平台_牛客网

题目描述:

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

Bessie has received N (1 <= N <= 50,000) chocolates from the bulls, but doesn't want to eat them too quickly, so she wants to plan out her chocolate eating schedule for the next D (1 <= D <= 50,000) days in order to maximize her minimum happiness level over the set of those days.
Bessie's happiness level is an integer that starts at 0 and halves (rounding down if necessary) over night as she sleeps. However, when she eats chocolate i, her happiness level increases by integer HiH_iHi​ (1 <= HiH_iHi​ <= 1,000,000). If she eats chocolates on a day, her happiness for that day is considered the happiness level after she eats the chocolates. Bessie insists that she eat the chocolates in the order that she received them.
If more than one optimal solution exists, print any one of them.
Consider a sequence of 5 chocolates to be eaten over a period of 5 days; they respectively bring happiness (10, 40, 13, 22, 7).

If Bessie eats the first chocolate (10 happiness) on the first day and then waits to eat the others, her happiness level is 10 after the first day.

Here is the complete schedule which turns out to maximize her minimum happiness:
  Day  Wakeup happiness   Happiness from eating   Bedtime happiness
   1            0                10+40                  50
   2           25                 ---                   25
   3           12                  13                   25
   4           12                  22                   34 
   5           17                   7                   24
The minimum bedtime happiness is 24, which turns out to be the best Bessie can do.

输入描述:

* Line 1: Two space separated integers: N and D
* Lines 2..N+1: Line i+1 contains a single integer: HiH_iHi​

输出描述:

* Line 1: A single integer, the highest Bessie's minimum happiness can be over the next D days
* Lines 2..N+1: Line i+1 contains an integer that is the day on which Bessie eats chocolate i

输入

5 5 
10 
40 
13 
22 
7 

输出

24
1
1
3
4
5 

题目大意:

 

解题思路:

典型的二分+检验答案。最大化最小值问题。

我们可以假设最小快乐指数,然后检查这个假设的快乐指数是否可达,检查的方式是每天如果快乐值足够,就不吃巧克力,否则吃一块,如果巧克力吃完了还不能达到假定的快乐指数,则这个快乐指数是不可达的。

提供两种二分的写法,具体细节看代码和注释。

代码1(CPP):

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e4 + 100;
const int INF = 0x3fffffff;
const int mod = 1000000007;
ll n, d, h[maxn], ans[maxn];

bool check(ll x) {
    ll v = 0;
    int p = 1;
    for (int i = 1; i <= d; i++) {
        v /= 2;
        while (v < x && p <= n) {
            v += h[p];
            ans[p] = i;
            p++;
        }
        if (v < x) {
            return false;
        }
    }
    for (; p <= n; p++) {  // 坑点,所有巧克力都必须吃完,所以如果最后有剩下的必须吃掉
        ans[p] = d;
    }
    return true;
}

void solve() {
    cin >> n >> d;
    ll l = 0, r = 0, k;
    for (int i = 1; i <= n; i++) {
        cin >> h[i];
        r += h[i];
    }
    while (l < r) {  // 写法一,不抛弃mid
        ll mid = (l + r + 1) / 2;  // 特别注意,不抛弃mid的写法求最大化最小值时,mid=(l+r+1)/2
        if (check(mid)) {
            l = mid;
        } else {
            r = mid - 1;
        }
    }
    k = l;
    check(k);  // 坑点,最后二分完毕之后,,ans数组里不一定是答案的状态
    cout << k << endl;
    for (int i = 1; i <= n; i++) {
        cout << ans[i] << endl;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << fixed;
    cout.precision(18);

    solve();
    return 0;
}

代码2(CPP):

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e4 + 100;
const int INF = 0x3fffffff;
const int mod = 1000000007;
ll n, d, h[maxn], ans[maxn];

bool check(ll x) {
    ll v = 0;
    int p = 1;
    for (int i = 1; i <= d; i++) {
        v /= 2;
        while (v < x && p <= n) {
            v += h[p];
            ans[p] = i;
            p++;
        }
        if (v < x) {
            return false;
        }
    }
    for (; p <= n; p++) {  // 坑点,所有巧克力都必须吃完,所以如果最后有剩下的必须吃掉
        ans[p] = d;
    }
    return true;
}

void solve() {
    cin >> n >> d;
    ll l = 0, r = 0, k;
    for (int i = 1; i <= n; i++) {
        cin >> h[i];
        r += h[i];
    }
    while (l <= r) {  // 写法二,抛弃mid
        ll mid = (l + r) / 2;
        if (check(mid)) {
            // 或者也可以在这里记录答案 k = mid
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    k = l - 1;  // 注意这种写法这里的答案不应该是l,应该是l - 1
    check(k);  // 坑点,最后二分完毕之后,,ans数组里不一定是答案的状态
    cout << k << endl;
    for (int i = 1; i <= n; i++) {
        cout << ans[i] << endl;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << fixed;
    cout.precision(18);

    solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值