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

本文探讨了一个关于春节收红包的数学问题,通过动态规划算法解决如何在父亲收红包和女儿阻止之间找到最优策略,以使父亲获得的红包金额最小。文章详细介绍了问题背景、输入输出格式、示例以及算法思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 sis_isi to tit_iti, inclusive, and contain wiw_iwi 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 sis_isi and tit_iti, inclusive, and he can’t collect any more envelopes until time did_idi (inclusive) after that. Here si≤ti≤dis_i≤t_i≤d_isitidi 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)(1≤n≤10^5, 0≤m≤200, 1≤k≤10^5)(1n105,0m200,1k105), 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,dis_i, t_i, d_isi,ti,di and wiw_iwi (1≤si≤ti≤di≤n,1≤wi≤109)(1≤s_i≤t_i≤d_i≤n, 1≤w_i≤10^9)(1sitidin,1wi109) — 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]d[i][j]表示前iii个时间点其中用了jjj次机会所能得到的最少金币。

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

d[di+1][j]=min(d[i][j]+wi)d[d_i+1][j]=min(d[i][j]+w_i)d[di+1][j]=min(d[i][j]+wi)
d[i+1][j+1]=min(d[i][j])d[i+1][j+1]=min(d[i][j])d[i+1][j+1]=min(d[i][j])

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值