P3817 小A的糖果(经典贪心)

发布时间 2024-01-08 01:20:46作者: 拍手称快

P3817 小A的糖果

题目思路

由题目可知,我们目标是把相邻两个的数求和进行判断,所以我们可以除了本身记录数据的一个数组(记为a)额外开一个数组(记为c)来记录两个数之和再进行操作。
那么简单思考
c1由a1和a2决定,我们需要对a1或者a2进行删减,那么再对a2进行删减时必然关联到c2,那么我们就可以得到结果,用到贪心思想,在遍历数组时对相邻c数组进行贪心求最优解,从相邻两个的最优解来推导至全部数据最优解。

贪心思路

我们先对第一个c1判断是否满足条件小于x,如果不能满足,那么我们就知道c1要开始减,那从a1,还是a2开始减呢?很简单,我们直接判断c2是否小于x,如果小于,那么减a2就是最优解,反之减a1,a2没有区别。

错误思路

思路1

没有注意到在c2小于x时a2是否可减,导致错误
错入代码如下:

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
ll a[N];
ll c[N];

int main() {
	ll b, x, ans = 0;
	cin >> b >> x;
	for (int i = 1; i <= b; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= b - 1; i++) {
		c[i] = a[i] + a[i + 1];
	}
	for (int i = 1; i <= b - 1; i++) {
		if (c[i] <= x) {
			continue;
		} else {
			if (c[i + 1] <= x) {
				while (c[i] > x) {
					c[i]--;
					ans++;
				}
			} else {
				while (c[i] > x) {
					c[i + 1]--;
					c[i]--;
					ans++;
				}
			}
		}
	}
	cout << ans;
	return 0;
}

思路2

改完思路1,发现居然有两个点超时了。
这里我们用while循环来进行模拟过程是一个非常愚蠢的过程,因为过程本身就是重复的,我们其实已经由深层判断,不需要再while遍历时判断。

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
ll a[N];
ll c[N];

int main() {
	ll b, x, ans = 0;
	cin >> b >> x;
	for (int i = 1; i <= b; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= b - 1; i++) {
		c[i] = a[i] + a[i + 1];
	}
	for (int i = 1; i <= b - 1; i++) {
		if (c[i] <= x) {
			continue;
		} else {
			if (c[i + 1] <= x) {	
				ans+=c[i]-x;			
			} else {
				while (c[i] > x) {
					if(a[i+1]==0){
					c[i]--;
					}else{
					c[i + 1]--;
					c[i]--;
					}	
					ans++;
				}
			}
		}
	}
	cout << ans;
	return 0;
}

正确代码

我们直接对需要减的数直接减,和对答案直接记录,不需要用while遍历,这样可以非常节约时间。

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
ll a[N];
ll c[N];

int main() {
	ll b, x, ans = 0;
	cin >> b >> x;
	for (int i = 1; i <= b; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= b - 1; i++) {
		c[i] = a[i] + a[i + 1];
	}
	for (int i = 1; i <= b - 1; i++) {
		if (c[i] <= x) {
			continue;
		} else {
			if (c[i + 1] <= x) {
				ans += c[i] - x;
			} else {
				if (c[i] - x <= a[i + 1]) {
					ans += c[i] - x;
					c[i + 1] -= c[i] - x;
				} else {
					ans += c[i] - x;
					c[i + 1] -= a[i + 1];
				}
			}
		}
	}
	cout << ans;
	return 0;
}