codeforces 1106E E. Lunar New Year and Red Envelopes (DP)

本文详细解析了Codeforces 1106E题目的解题思路与算法实现,通过动态规划的方法,在时间线中选择最优策略,以最小化领红包的总价值。适合对算法竞赛感兴趣或希望提高动态规划技能的读者。

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

题面链接:https://codeforces.com/contest/1106/problem/E

难度:2100

题意:现在有长度为N的时间线 A现在要领红包 有K个红包 每个红包 四个属性 这个红包只在[s,t]的时间区间内出现,并且领了这个红包后在D的时间前不能领红包了(包括D时间)这个红包价值W。他在每个时间上领W最大的红包,若果W相同领D大的。现在B可以打断A领红包M次。打断的意思是在某一个时间让他不能领红包。M最大为200。问B能采取什么策略让A能领的W合最小

思路:这题思路很简单 就是选取至多M个时间点打断他 让他的红包钱最少。

很清楚这个dp有两个转移 :每次他能领红包的时候 可以打断 直接转移到 D+1

要不就是打断他 让他转移到 i+1

dp[i][j] 表示在i的时间线之前打断j次A能拿到最少的钱为多少

注意 当他在i这个时间点 没红包选时 只能直接转到下一个i

 

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct node{
	ll t,d,w;
    operator < (const node &n1)const{
        if(w==n1.w) return d<n1.d;
        return w<n1.w;
	}
}arr[100050];

vector<int> pos[100005];
long long dp[100050][205];

int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    priority_queue <node> q1;


    for(int i=0;i<k;i++){
        ll s;
        scanf("%lld%lld%lld%lld",&s,&arr[i].t,&arr[i].d,&arr[i].w);
        pos[s].push_back(i);
    }

    for(int i=0;i<=n+1;i++){
        for(int j=0;j<=m;j++){
            dp[i][j] = 1<<30;
            dp[i][j] *= 1<<30;
        }
    }
    for(int i=0;i<=m;i++){
        dp[1][i] = 0;
    }

    for(int i=1;i<=n;i++){
        for(auto tmp : pos[i]){
            q1.push(arr[tmp]);
        }

        ll d=-1,w=-1;
        while(!q1.empty()){
            node tmp = q1.top();
            q1.pop();

            int t = tmp.t;

            if(t<i) continue;

            d = tmp.d;
            w = tmp.w;
            q1.push(tmp);

            break;
        }

        d++;
        for(int j=0;j<=m;j++){
            if(!d){
                dp[i+1][j] = min(dp[i+1][j],dp[i][j]);
                continue;
            }
            dp[d][j] = min(dp[i][j] + w,dp[d][j]);
            dp[i+1][j+1] = min(dp[i+1][j+1] , dp[i][j]);
        }
    }

    ll ans = 1<<30;
    ans *= ans;
    for(int i=0;i<=m;i++){
        ans = min(ans,dp[n+1][i]);
    }
    cout<<ans;

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值