Codeforces-1106E:Lunar New Year and Red Envelopes(DP+优先队列)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/86738613

E. Lunar New Year and Red Envelopes
time limit per test 3 seconds
memory limit per test 256 megabytes
input standard input
output standard output
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 s i s_i to t i t_i , inclusive, and contain w i w_i 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 s i s_i and t i t_i , inclusive, and he can’t collect any more envelopes until time d i d_i (inclusive) after that. Here s i t i d i s_i≤t_i≤d_i 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 1 0 5 , 0 m 200 , 1 k 1 0 5 ) (1≤n≤10^5, 0≤m≤200, 1≤k≤10^5) , 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 s i , t i , d i s_i, t_i, d_i and w i w_i ( 1 s i t i d i n , 1 w i 1 0 9 ) (1≤s_i≤t_i≤d_i≤n, 1≤w_i≤10^9) — 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
input
5 0 2
1 3 4 5
2 5 5 8
output
13
input
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
output
2
input
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
output
11

思路:很明显DP。 d [ i ] [ j ] d[i][j] 表示前 i i 个时间点其中用了 j j 次机会所能得到的最少金币。

但是由于Bob每次要优先取 w i w_i 最大,其次是取 d i d_i 最大。所以要使用滑动窗口,在 i i 这点,将所有满足条件的信封放入优先队列,然后再进行转移。当然选择的时候,不满足条件的信封直接舍弃即可。

d [ d i + 1 ] [ j ] = m i n ( d [ i ] [ j ] + w i ) d[d_i+1][j]=min(d[i][j]+w_i)
d [ i + 1 ] [ j + 1 ] = m i n ( d [ i ] [ j ] ) d[i+1][j+1]=min(d[i][j])

但是如果当前没有满足条件的信封即优先队列为空时,这时候就要把当前时间点的状态保留至下一个时间点。
f o r ( j = 0 ; j < = M ; j + + ) d [ i + 1 ] [ j ] = d [ i ] [ j ] ; for(j=0;j<=M;j++)d[i+1][j]=d[i][j];

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct lenka
{
    ll s,t,d,w;
    bool operator<(const lenka& q)const
    {
        if(q.w!=w)return q.w>w;
        return q.d>d;
    }
}A[MAX];
int cmp(const lenka& p,const lenka& q){return p.s<q.s;}
void Min(ll &x,ll y){if(y==-1)return;x=(x==-1?y:min(x,y));}
ll d[MAX][201];
priority_queue<lenka>p;
int main()
{
    int N,M,K;
    cin>>N>>M>>K;
    for(int i=1;i<=K;i++)scanf("%lld%lld%lld%lld",&A[i].s,&A[i].t,&A[i].d,&A[i].w);
    sort(A+1,A+K+1,cmp);
    memset(d,-1,sizeof d);
    d[1][0]=0;
    int now=1;
    for(int i=1;i<=N;i++)
    {
        while(now<=K&&A[now].s<=i)p.push(A[now]),now++;
        while(!p.empty()&&p.top().t<i)p.pop();
        if(p.empty())//没有信封可选,保留状态至下一时间点
        {
            for(int j=0;j<=M;j++)Min(d[i+1][j],d[i][j]);
            continue;
        }
        lenka Q=p.top();
        for(int j=0;j<=M;j++)
        {
            if(d[i][j]==-1)continue;
            Min(d[min(N+1ll,Q.d+1)][j],d[i][j]+Q.w);
            if(j<M)Min(d[min(N+1,i+1)][j+1],d[i][j]);
        }
    }
    printf("%lld\n",max(0ll,*min_element(d[N+1],d[N+1]+M+1)));//硬是忘了有-1,忘记判,结果还过了pretest,WA在了SystemTest
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/86738613