【c++】NC24724 [USACO 2010 Feb S] Chocolate Eating(二分查找)

链接:登录—专业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 H_i (1 <= H_i <= 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.

题意

贝西从公牛那里收到了N块巧克力。 她不想把它们马上吃完,而是打算制定一个计划,使得在接下来的D天里,使得每天的最小幸福指数最大。 贝西的幸福指数可以用一个整数来衡量,一开始的时候是0当她每天晚上睡觉的时候,幸福指数会减半(奇数时向下取整)。贝西把她的巧克力按照收到的时间排序,并坚持按照这个顺序来吃巧克力。当她吃掉第i块巧克力的时候,她的幸福指数会增加 H_i。她那天的幸福值被认为是她吃完巧克力后的幸福水平。每天可以吃任意多块巧克力,如何帮助贝西合理安排,使得D天内她的最小幸福指数最大呢?

输入描述:

  • Line 1: Two space separated integers: N and D

  • Lines 2..N+1: Line i+1 contains a single integer: H_i

输出描述:

  • 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

示例1

输入

 5 5 
 10 
 40 
 13 
 22 
 7 

输出

 24
 1
 1
 3
 4
 5

注意

巧克力必须全部吃完!

 Consider a sequence of 5 chocolates to be eaten over a period of 2 days; they respectively bring happiness (24, 11, 1, 1, 1).
 最小幸福指数最大情形:
   Day  Wakeup happiness   Happiness from eating   Bedtime happiness
    1            0                  24                   24
    2           12            11+1+1+1                   26
 The minimum bedtime happiness is 24, which turns out to be the best Bessie can do.
 本来最后一天吃11+1这两块就可以了,但是根据题意必须都吃完
 ​
 非最优解情形举例:
   Day  Wakeup happiness   Happiness from eating   Bedtime happiness
    1            0               24+11                   35
    2           17               1+1+1                   20
 The minimum bedtime happiness is 20.

代码

#include<iostream>
using namespace std;
/*


*/
#define int long long
const int MAX_NUM = 5e10;
const int SIZE = 5e4 + 10;
int a[SIZE],eat[SIZE];
int n, d, h;

bool check(int min_happy) {
	int j = 0,//代表巧克力下标
		today_happiness=0;//某一天的幸福指数
	for (int i = 1; i <= d; i++)
	{
		today_happiness >>= 1;//第二天起床,幸福指数会减半
		while (today_happiness < min_happy) {//还要继续吃巧克力
			if (j==n)//巧克力吃完了
			{
				if (d==i)//在最后一天把巧克力吃完才正好达到最低幸福指数
				{
					return today_happiness >= min_happy;
				}
				else
				{
					//在预计的天数之前就吃完了,显然最低幸福指数太高了
					return false;
				}
			}
			today_happiness += a[j];
			eat[j++] = i;
		}
	}
	//没吃完的巧克力要在最后一天全部吃完(必须要加)
	for (;j < n; j++)
	{
		eat[j] = d;
	}

	return today_happiness >= min_happy;//true 表示min_happy还可以更大
}

signed main()
{
    cin >> n >> d;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	int left = 1, right = MAX_NUM, mid,ans=-1;
	//在幸福指数的取值范围内二分查找
	while (left<=right)
	{
		mid = (left + right) >> 1;
		if (check(mid))
		{
			ans = max(ans, mid);
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	//最后一次判断的答案不是最终答案,因此跳出循环之后要用最终答案再判断一次
	//上一次left=mid+1∴上一次(正确答案)mid=left-1
	//这样生成的flag数组才是最终答案对应的数组
	check(left-1);
	cout << ans << endl;
	for (int i = 0; i < n; i++)
	{
		cout << eat[i] << endl;
	}
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深|码|洞|悉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值