P3817

P 3817 A P3817 小A的糖果

  • 题目
    P3817
  • 题意
  • 分析
    贪心的思想可知,变动中间的糖果会比只变动两边的糖果所需的次数要少,所以可以划分 n 1 n-1 个阶段,每个阶段只关心当前阶段和上一个阶段。当处于下一个阶段时,就是当前的阶段和下一个阶段了,互不影响。
    因此 a n s = i = 2 n a [ i ] + a [ i 1 ] x ans = {\sum^{n}_{i= 2}} a[i]+a[i-1]-x ,这个式子代表如果当前阶段的糖果数加上上一个阶段的糖果数大于所给 k k ,那么就需要吃掉相差的数值。当前阶段的糖果数就需要变动,贪心的思想为了使得下一个阶段尽量小(这样尽可能统计少的答案或不统计),需要将相差的数值全部在当前阶段的 a [ i ] a[i] 上变动,但是 a [ i ] a[i] 不为负,所以如果 a [ i ] < a [ i ] + a [ i 1 ] x a[i] < a[i]+a[i-1]-x a [ i ] = 0 a[i] = 0 即可,表示先让 a [ i ] a[i] 到达最小,多处来的部分在 a [ i 1 ] a[i-1] 上减去。
  • 代码
/*
  独立思考
  一个题不会做,收获5%,写了代码10%,提交对了30%,总结吃透了这个题才是100%.
*/
#include<bits/stdc++.h>
using namespace std;
template <typename T>
void read(T &x)
{
	x = 0;
	char c = getchar();
	int sgn = 1;
	while (c < '0' || c > '9') {if (c == '-')sgn = -1; c = getchar();}
	while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
	x *= sgn;
}
template <typename T>
void out(T x)
{
	if (x < 0) {putchar('-'); x = -x;}
	if (x >= 10)out(x / 10);
	putchar(x % 10 + '0');
}
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a;}
const int N = 1e5 + 5;
int a[N];
int main ()
{
	int n, x;
	cin >> n >> x;
	for (int i = 1; i <= n; i++) cin >> a[i];
	ll ans = 0;
	for (int i = 2; i <= n; i++)
	{
		if (a[i] + a[i - 1] > x)
		{
			ans += a[i] + a[i - 1] - x;
			if (a[i] > a[i] + a[i - 1] - x)
				a[i] -= a[i] + a[i - 1] - x;
			else a[i] = 0;
		}
	}
	cout << ans << endl;
	return 0 ;
}
  • 方法
    贪心
  • 总结
    当时写的时候考虑了 a [ i ] a [ i 1 ] a [ i + 1 ] a[i]、a[i-1]、a[i+1] 这三个阶段的情况,事实上只需要考虑两个阶段就可以了。影响当前阶段的答案的只会是前一个阶段,后一个阶段也考虑的话,不满足递推的特性。以后要注意。

猜你喜欢

转载自blog.csdn.net/strategist_614/article/details/88382432