Description:
过年老爸去拿红包女儿要干扰他。有n个时间点,m次干扰机会,k个红包。每个红包有四个属性值s,t,d,w。
s和t分别是取红包的开始和结束时间,在这个时间外不能拿该红包。d是指若拿了该红包则在时间d之前都不能拿下一个红包,w是指红包的价值。
现在老爸在时间点1上只会贪心地去拿红包:1.每次会优先取当前能取得价值最大的红包2.若两红包都达到当前最大值,则选择d大的那个
女儿有m次机会干扰老爸,每次都在一个时间点上,可以使得老爸当前时刻无法拿任何红包。
问最后老爸最少能拿到多少钱。
Input:
n,m,k
si,ti,di,wi(for 1<=i<=k)
Output:
输出答案
Analysis:
考虑先模拟,求出爸爸在任何时刻的选择,因为这是女儿如何干扰都不会变得。具体来说是先把红包的开始和结束事件记录,然后按照事件的顺序,维护一个有序multiset,同时记录每个时刻的选择。
接下来直接dp就行, 设dp[i][j]表示,使用了i次干扰,到达了时刻j的获得的最少价值。状态转移方程为
dp[i+1][j + 1] = min(dp[i+1][j + 1], dp[i][j]);
dp[i][seq[j].d + 1] = min(dp[i][seq[j].d+1],dp[i][j]+seq[j].w);
学会了两点:1.用map<obj,num>做multiset 2.一种压缩空间写动态规划的方式
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<ctime>
#include<cstring>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int maxn = 100005;
const int MOD = 1e9+7;
const double eps = 1e-6;
int n, m, k;
struct Event {
int d, t, w;
bool operator<(const Event & rhs)const {
return w > rhs.w || (w == rhs.w&&d > rhs.d);
}
Event(int d,int t,int w):d(d),t(t),w(w) {}
Event(){}
};
vector<Event> e[maxn],seq;
map<Event, int> cur;
LL dp[2][maxn];
void insert(Event x) {
if (cur.count(x)) {
cur[x]++;
}
else cur[x] = 1;
}
void erase(Event x) {
cur[x]--;
if(cur[x]==0)
cur.erase(x);
}
int main()
{
//freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin);
//freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout);
while (scanf("%d%d%d", &n, &m, &k)==3) {
_rep(i, 1, n) {
e[i].clear();
}
_for(i, 0, k) {
int s, t, d, w;
scanf("%d%d%d%d", &s, &t, &d, &w);
e[s].push_back(Event(d, 1, w));
e[t + 1].push_back(Event(d, -1, w));
}
cur.clear();
seq.resize(n + 1);
_rep(i, 1, n) {
for (auto it :e[i] ) {
if (it.t == 1)insert(it);
else erase(it);
}
if (cur.size()) {
seq[i] = (*cur.begin()).first;
}
else seq[i] = Event(i, 0, 0);
}
memset(dp, 0x3f3f3f3f3f3f3f3fLL, sizeof(dp));
dp[0][1] = 0;
LL ans = 0x3f3f3f3f3f3f3f3fLL;
for (int i = 0; i <= m; ++i) {
memset(dp[(i ^ 1) & 1], 0x3f3f3f3f3f3f3f3fLL, sizeof(dp[(i ^ 1)&1]));
for (int j = 1; j <= n; ++j) {
dp[(i ^ 1) & 1][j + 1] = min(dp[(i ^ 1) & 1][j + 1], dp[i & 1][j]);
dp[i & 1][seq[j].d + 1] = min(dp[i & 1][seq[j].d+1],dp[i&1][j]+seq[j].w);
}
ans = min(ans, dp[i & 1][n + 1]);
}
cout << ans << endl;
}
return 0;
}