小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

输出格式

输出一行一个整数,代表最少要吃掉的糖果的数量。

数据规模与约定
  • 对于 30 % 30\% 30% 的数据,保证 n ≤ 20 n \leq 20 n20 a i , x ≤ 100 a_i, x \leq 100 ai,x100
  • 对于 70 % 70\% 70% 的数据,保证 n ≤ 1 0 3 n \leq 10^3 n103 a i , x ≤ 1 0 5 a_i, x \leq 10^5 ai,x105
  • 对于 100 % 100\% 100% 的数据,保证 2 ≤ n ≤ 1 0 5 2 \leq n \leq 10^5 2n105 0 ≤ a i , x ≤ 1 0 9 0 \leq a_i, x \leq 10^9 0ai,x109

思路

为了保证吃掉的糖果最少,使用贪心算法。例如有三个罐子都超过了规定的大小的,吃中间罐子肯定是最少的,因为这样前后两个相加的数量都减少了。而如果是吃两侧明显会吃掉更多。因此思路就是从左向右遍历,如果相加超过了规定大小就吃掉右侧罐子,同理如果是从左向右遍历就吃左边罐子。为了加快算法速度使用从左向右遍历,这样可以不用开辟额外的空间。

需要注意的是有可能出现这样的情况:需要吃掉的个数大于右侧的罐子中糖果数量。并且结果有可能会超过int型大小。

代码实现

#include
using namespace std;
int main(){
	long long int ans=0;
	//事实上每次判断需要吃掉的糖果数只需要当前和前一个罐子数据,可直接定义两个变量来代替数组
	int n,x,data[100001];
	cin>>n>>x;
	//先输入第一个罐子,方便计算下一个罐子需要吃掉的数量
	cin>>data[0];
	//开始输入,并计算每个罐子需要吃掉的糖果数量
	for(int i=1;i<n;i++){
		cin>>data[i];
		//判断和前一个罐子相加是否超过规定的数量
		if(data[i]+data[i-1]>x){
			//最终结果加上被吃掉的数量
		    ans+=data[i]+data[i-1]-x;
		    //判断当前罐子中糖果数量是否小于当前需要吃掉的糖果数量
		    if(data[i]>=data[i]+data[i-1]-x)
		    	//如果不小于直接吃
		    	data[i]=data[i]-(data[i]+data[i-1]-x);
		    else
		    	//如果小于就将当前罐子糖果吃完,剩下的在前一个罐子吃。
		    	//直接设置当前罐子数量为0即可,前一个罐子不用设置,因为后面只需要前一个罐子糖果数据
		    	data[i]=0;
		}
	}
	cout<<ans;
}

你可能感兴趣的:(算法,笔记)