贪心的证明我没做,只是简单的想了一下如果能尽可能的积累优惠劵就可以拿到更大的优惠的想法,然后简单模拟了两种做法。
第一种,有就用
原价 | 1 | 2 | 3 | 3 | 4 | 总 |
---|---|---|---|---|---|---|
支付 | 1 | 2-1 | 3 | 3-1 | 4 | 11 |
第二种,留给贵的用
原价 | 1 | 2 | 3 | 3 | 4 | 总 |
---|---|---|---|---|---|---|
支付 | 1 | 2 | 3 | 3 | 4-1-1-1-1 | 9 |
嗯,然后代码实现
定义i和j分别表示当前最便宜奶茶和最贵奶茶for (i = 1, j = n; i < j; i++)
最便宜的奶茶当然要付全款,然后把优惠累计在j上
cnt += a[i];a[j]–;
那么如果最贵的奶茶被变成0了,就可以把优惠用在第二便宜的奶茶上;
if (a[j] == 0) j–;
因为我的条件是i<j,这样的话退出一定是i>=j了,其实这里还有两种情况,就是最贵的还没有被优惠完,和正好优惠完
最贵的还没有被优惠完:1 1 5,这时候i=j=3,所以a[j]的钱还是需要支付cnt+=a[j]
正好优惠完:1 1 1 ,这时候i=j=2,但是第2杯还是要花钱的cnt+=a[j]
正好优惠完:1 1 1 1,这时候i=3,j=2,在这时候a[j]里的变量就没有什么用了
所以我想到了一个更妙的做法,把用原价买完奶茶后的值改为0,这样就不会出问题了
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e3 + 5;
int n, i, j, cnt;
int a[N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (i = 1; i <= n; i++)cin >> a[i];
for (i = 1, j = n ; i < j; i++) {
cnt += a[i]; //原价买了最便宜的奶茶
a[i] = 0;//防止重复计算
a[j]--;//优惠卷给了最贵的奶茶
if (a[j] == 0) j--;
}
cnt += a[j];
cout << cnt;
return 0;
}
比题解区的代码快
以上仅我个人观点,欢迎各位大佬指正