题意:
有n个红包,每个红包可以在[si,ti]的时间内拾起,拾起后获得wi元,但是到di这个时刻都不能再获取其他红包
a非常贪心,他在每一时刻,如果这个时刻可以拾起红包,它会拾起金额最大的,如果同时有多个金额最大的
他会拾起di最大的
有m次干扰他的机会,每次干扰他使得他在某个时刻不能拾起红包他的女儿可以
如果他的女红采用最优操作,他最少获得多少金钱
思路:
我们发现在某个时刻如果可以拾起红包,那么这个红包已经确定,可以用优先队列预处理
再考虑dp[i][j]表示在第i个时刻,用了j次机会的最少金币dp[i][j]表示在第i个时刻,用了j次机会的最少金币
有两个转移有两个转移
一个是这个时刻如果没有红包可以拿那么一个是这个时刻如果没有红包可以拿那么
dp[i+1][j]=min(dp[i+1][j],dp[i][j])dp[i+1][j]=min(dp[i+1][j],dp[i][j])
如果有红包可以拿
dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j])dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j])
dp[di+1][j]=min(dp[di+1][j],dp[i][j]+wi)
【代码】
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll maxn = 1e5 + 6;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct node {
ll s, t, d, w;
bool operator <(const node &r)const {
if (w == r.w)return d < r.d;
return w < r.w;
}
}k[maxn];
ll gt[maxn];
ll nxt[maxn];
ll dp[maxn][202];
ll cmp(node &a, node &b) {
return a.s < b.s;
}
int main() {
ll n, m, p;
while (~scanf("%lld%lld%lld", &n, &m, &p)) {
for (ll i = 1; i <= p; i++) {
scanf("%lld%lld%lld%lld", &k[i].s, &k[i].t, &k[i].d, &k[i].w);
}
sort(k + 1, k + 1 + p, cmp);
priority_queue<node>q;
ll cnt = 1;
for (ll i = 1; i <= n; i++) {
while (cnt <= p && k[cnt].s <= i) {
q.push({ k[cnt++] });
}
while (q.size() && q.top().t < i)q.pop();
if (q.size()) {
node tmp = q.top();
gt[i] = tmp.w;
nxt[i] = tmp.d + 1;
}
else {
gt[i] = 0;
nxt[i] = i + 1;
}
}
memset(dp, inf, sizeof(dp));
for (ll i = 0; i <= m; i++)dp[1][i] = 0;
for (ll i = 1; i <= n; i++) {
for (ll j = 0; j <= m; j++) {
if (gt[i]) {
dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j]);
dp[nxt[i]][j] = min(dp[nxt[i]][j], dp[i][j] + gt[i]);
}
else {
dp[i + 1][j] = min(dp[i + 1][j], dp[i][j]);
}
}
}
ll res = inf;
for (ll i = 0; i <= m; i++) {
res = min(res, dp[n + 1][i]);
}
printf("%lld\n", res);
}
}