【BZOJ】2697: 特技飞行

题意

\(k(1 \le k \le 300)\)种物品,价值分别为\(c_i(0 \le c_i \le 1000)\)。有\(n(1 \le n \le 1000)\)分钟,每分钟可以选择一个物品\(i\),价值为距离上次选择该物品的时间 * \(c_i\)。求最大价值。

分析

发现对于一种物品,价值为\(c_i * \sum_{j=2}^{a} (t_j-t_{j-1}) = c_i * (t_a-t_1)\)\(t_i\)表示第\(i\)次选这个物品的时间。这样,我们只需要为每一个物品找到一个开始和结束时间的时间即可。
由于考虑任意两种物品及其位置对其它的物品的贡献无影响,所以我们考虑任意两种物品。
对于两种物品\(i, j\),假设\(c_i \ge c_j\),他们开始和结束时间分别为\(l_i, r_i\)\(l_j, r_j\),则最优解中肯定\(l_i < l_j, r_j < r_i\),证明如下:
首先显然肯定不可能\(l_j < l_i, r_i < r_j\)
假设\(l_i < l_j, r_i < r_j\)\(l_j < l_i, r_j < r_i\)证明类似),则可以证明将\(r_i, r_j\)交换后更优(证明大简单,略)。
所以我们将物品排序后,一个个取即可。

题解

所以贪心地取即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500005;
int n, k, a[N];
int main() {
    scanf("%d%d", &n, &k);
    for(int i=1; i<=k; ++i) {
        scanf("%d", &a[i]);
    }
    sort(a+1, a+1+k);
    int num=n-1;
    ll ans=0;
    for(int i=k; i; --i) {
        if(num<0) {
            break;
        }
        ans+=(ll)num*a[i];
        num-=2;
    }
    printf("%lld\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/iwtwiioi/p/4985756.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值