Lunar New Year is approaching, and Bob is going to receive some red envelopes with countless money! But collecting money from red envelopes is a time-consuming process itself.
Let’s describe this problem in a mathematical way. Consider a timeline from time 1 to n. The i-th red envelope will be available from time si to ti, inclusive, and contain wi coins. If Bob chooses to collect the coins in the i-th red envelope, he can do it only in an integer point of time between si and ti, inclusive, and he can’t collect any more envelopes until time di (inclusive) after that. Here si≤ti≤di holds.
Bob is a greedy man, he collects coins greedily — whenever he can collect coins at some integer time x, he collects the available red envelope with the maximum number of coins. If there are multiple envelopes with the same maximum number of coins, Bob would choose the one whose parameter d is the largest. If there are still multiple choices, Bob will choose one from them randomly.
However, Alice — his daughter — doesn’t want her father to get too many coins. She could disturb Bob at no more than m integer time moments. If Alice decides to disturb Bob at time x, he could not do anything at time x and resumes his usual strategy at the time x+1 (inclusive), which may lead to missing some red envelopes.
Calculate the minimum number of coins Bob would get if Alice disturbs him optimally.
Input
The first line contains three non-negative integers n, m and k (1≤n≤105, 0≤m≤200, 1≤k≤105), denoting the length of the timeline, the number of times Alice can disturb Bob and the total number of red envelopes, respectively.
The following k lines describe those k red envelopes. The i-th line contains four positive integers si, ti, di and wi (1≤si≤ti≤di≤n, 1≤wi≤109) — the time segment when the i-th envelope is available, the time moment Bob can continue collecting after collecting the i-th envelope, and the number of coins in this envelope, respectively.
Output
Output one integer — the minimum number of coins Bob would get if Alice disturbs him optimally.
Examples
inputCopy
5 0 2
1 3 4 5
2 5 5 8
outputCopy
13
inputCopy
10 1 6
1 1 2 4
2 2 6 2
3 3 3 3
4 4 4 5
5 5 5 7
6 6 6 9
outputCopy
2
inputCopy
12 2 6
1 5 5 4
4 6 6 2
3 8 8 3
2 9 9 5
6 10 10 7
8 12 12 9
outputCopy
11
Note
In the first sample, Alice has no chance to disturb Bob. Therefore Bob will collect the coins in the red envelopes at time 1 and 5, collecting 13 coins in total.
In the second sample, Alice should disturb Bob at time 1. Therefore Bob skips the first envelope, collects the second one and can not do anything after that. So the answer is 2.
题意:
给你长度为n的时间线,女儿可以捣乱的时间长度,红包的个数,接下来是k个红包可以领取的起始时间,终止时间,和领取这个红包之后他至少要等到di+1的时间才能领取下一个红包的di,和这个红包里面有多少钱。如果能领红包他会领金额最大的,多个会领di最大的。在女儿捣乱的时候不能领红包,问你这个人最后最少能领到多少钱。
题解:
优先队列存放当前的红包,dp[i][j]表示在第i个时间点,女儿捣乱j分钟最少能领多少钱,那么有两种情况:现在没有红包领,那么这个状态就要继承到下一个状态,注意不是从上一个继承下来,因为在i的时候是有红包的,在i+1的时候才没有,所以这种情况的状态转移方程是dp[i+1][j]=min(dp[i+1][j],dp[i][j])(我一开始一直没想清楚这块,所以怎么都过不去,卡在第7个),还有一种就是现在有红包的时候,但是如果没有这个状态,就是说在第i个时间女儿吵闹j次是不可能的,那么就continue,否则就有两种情况:这时候女儿吵闹,或者领了当前最优的红包:
dp[i+1][j+1]=min(dp[i][j],dp[i+1][j+1]);
dp[now.d+1][j]=min(dp[now.d+1][j],dp[i][j]+now.w);
最后因为是将状态转移到di+1这里,所以n也要转移到n+1这里,前提是n+1没有状态。
(太坑啦,打注释的地方真的就是想不到一直卡住)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
const ll inf=1e18;
ll dp[N][205];
struct node
{
int sta,fin,d;
ll w;
bool operator< (const node& a)const
{
if(w!=a.w)
return w<a.w;
return d<a.d;
}
}p[N];
bool cmp(node a,node b)
{
return a.sta<b.sta;
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
scanf("%d%d%d%lld",&p[i].sta,&p[i].fin,&p[i].d,&p[i].w);
sort(p+1,p+1+k,cmp);
for(int i=1;i<=n+1;i++)
for(int j=0;j<=m;j++)
dp[i][j]=inf;
dp[p[1].sta][0]=0;
int pos=1;
priority_queue<node>Q;
node now;
int flag;
for(int i=p[1].sta;i<=n;i++)
{
while(p[pos].sta==i)
Q.push(p[pos++]);
while(!Q.empty()&&Q.top().fin<i)
Q.pop();
flag=0;
if(Q.empty())
flag=1;
else
now=Q.top();
for(int j=0;j<=m;j++)
{
if(!flag&&dp[i][j]==inf)
continue;
if(flag)
dp[i+1][j]=min(dp[i][j],dp[i+1][j]);//不能是dp[i-1][j]因为i-1这个状态队列里是有东西的,所以要从这个状态开始向下
else
{
dp[i+1][j+1]=min(dp[i][j],dp[i+1][j+1]);
dp[now.d+1][j]=min(dp[now.d+1][j],dp[i][j]+now.w);
}
}
}
for(int i=0;i<=m;i++)
{
if(dp[n+1][i]!=inf)
continue;
else
dp[n+1][i]=dp[n][i];
}
ll minn=inf;
for(int i=0;i<=m;i++)
minn=min(minn,dp[n+1][i]);
printf("%lld\n",minn);
return 0;
}