P3817 小A的糖果(经典贪心)
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;
}