【题解】【洛谷P3817】【贪心】——小A的糖果
小A的糖果
题目描述
小 A 有 n n n 个糖果盒,第 i i i 个盒中有 a i a_i ai 颗糖果。
小 A 每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中糖的个数之和都不大于 x x x,至少得吃掉几颗糖。
输入格式
输入的第一行是两个用空格隔开的整数,代表糖果盒的个数 n n n 和给定的参数 x x x。
第二行有 n n n 个用空格隔开的整数,第 i i i 个整数代表第 i i i 盒糖的糖果个数 a i a_i ai。
输出格式
输出一行一个整数,代表最少要吃掉的糖果的数量。
输入输出样例
输入 #1
3 3
2 2 2
输出 #1
1
输入 #2
6 1
1 6 1 2 0 4
输出 #2
11
输入 #3
5 9
3 1 4 1 5
输出 #3
0
提示
样例输入输出 1 解释
吃掉第 2 盒中的一个糖果即可。
样例输入输出 2 解释
第 2 盒糖吃掉 6 6 6 颗,第 4 盒吃掉 2 2 2 颗,第 6 盒吃掉 3 3 3 颗。
数据规模与约定
- 对于 30 % 30\% 30% 的数据,保证 n ≤ 20 n \leq 20 n≤20, a i , x ≤ 100 a_i, x \leq 100 ai,x≤100。
- 对于 70 % 70\% 70% 的数据,保证 n ≤ 1 0 3 n \leq 10^3 n≤103, a i , x ≤ 1 0 5 a_i, x \leq 10^5 ai,x≤105。
- 对于 100 % 100\% 100% 的数据,保证 2 ≤ n ≤ 1 0 5 2 \leq n \leq 10^5 2≤n≤105, 0 ≤ a i , x ≤ 1 0 9 0 \leq a_i, x \leq 10^9 0≤ai,x≤109。
1.思路解析
大体思路:循环判断每一组相邻的糖果盒( a [ i ] a[i] a[i]和 a [ i + 1 ] a[i+1] a[i+1])。如果它们的糖果数量的总和超过了上限。就一直吃,直到没有超出上限为止。问题是:吃哪一个盒子之中的糖果好呢?
贪心策略
:遍历所有(每两个相邻的糖果盒为一组)糖果盒,如果超过上限就尽量挑右边的吃,以便影响到后面的糖果盒。
证明
(反证法):假设每一次挑左边的吃可以达成最优解,直接看看这一组样例:
3 3
2 2 2
用我们猜想的贪心策略,得到的答案是:
1 1 2
2
为什么会出现这种情况呢?我们的预期是:每一组超出上限的糖果盒吃完后都刚好达到上限。但是这样的贪心策略就导致了已经处理完的组有可能还会受影响
。无法达成最优解。假设错误,贪心策略正确。
如上图所示,当我们改变a[2]
时,a[1]
和a[3]
都会受到影响。因此,如果超过上限就尽量挑右边的吃可以达成最优解。
2.AC代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n,x,a[100010],ans=0;
cin>>n>>x;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++)
if(a[i]+a[i+1]>=x)//如果超出上限
{
int num=a[i]+a[i+1]-x;//计算超出的数量
ans+=num;
if(a[i+1]<num)//如果右边的不够减,左边的也要减
a[i]-=a[i+1]-num,a[i+1]=0;
else a[i+1]-=num;//否则就直接减右边的
}
cout<<ans;
return 0;
}
喜欢就订阅此专辑吧!
【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。
欢迎扫码关注蓝胖子编程教育