cf1106E 线性dp+multiset

之前看错题目了,以为父亲的选择时按最大收益来的。结果并不是

/*
注意题目中说只要某个时间父亲可以取得红包,他就取硬币数最多同时耗时最小的那个
就是不管后续如何,不一定满足最大收益
dp[i][j]表示时间i被干扰j次所得的最小收益
dp[i][j]=dp[a+1][j]+b; <a,b>是时间i可取的价值最大同时耗时最小的红包,这是必定取的
dp[i][j]=min(dp[i][j],dp[i+1][j-1])决定是否进行干扰
由状态转移方程可以看出,前面时间的状态是由后面时间的状态取得的,所以外层i循环从后往前
*/

#include<bits/stdc++.h>
#include<set>
#include<vector>
using namespace std;
#define maxn 100005
#define ll long long 
ll dp[maxn][205],n,m,k;
vector<pair<ll,ll> >S[maxn],E[maxn];
multiset<pair<ll,ll> >s;//默认是从小到大排序的,由于要取出的是价值最大的元素,所以在存入时把w存为-w 

int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++){
        ll s,t,d,w;
        cin>>s>>t>>d>>w;
        S[s].push_back(make_pair(-w,-d));
        E[t].push_back(make_pair(-w,-d));
    }
    
    memset(dp,0,sizeof dp);
    for(int i=n;i>=1;i--){
        for(int j=0;j<E[i].size();j++)s.insert(E[i][j]);
        pair<ll,ll> t=make_pair(0,0);
        ll a,b;
        if(!s.empty()){
            t=*s.begin();
            b=-t.first;a=-t.second+1;
        }
        else  a=i+1,b=0;
        for(int j=0;j<=m;j++){
            dp[i][j]=dp[a][j]+b;//未被干扰的决策 
            if(j)dp[i][j]=min(dp[i][j],dp[i+1][j-1]); 
        }
        for(int j=0;j<S[i].size();j++)s.erase(s.find(S[i][j]));
    } 
    printf("%lld\n",dp[1][m]);
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10345661.html