LeetCode 5660. 最多可以参加的会议数目 II(dp)

题意:
给你一个 events 数组,其中 events[i] = [startDayi, endDayi, valuei] ,
表示第 i 个会议在 startDayi 天开始,第 endDayi 天结束,
如果你参加这个会议,你能得到价值 valuei 。
同时给你一个整数 k 表示你能参加的最多会议数目。

你同一时间只能参加一个会议。
如果你选择参加某个会议,那么你必须 完整 地参加完这个会议。
会议结束日期是包含在会议内的,
也就是说你不能同时参加一个开始日期与另一个结束日期相同的两个会议。

请你返回能得到的会议价值 最大和 。

数据范围:
1 <= k <= events.length
1 <= k * events.length <= 1e6
1 <= startDayi <= endDayi <= 1e9
1 <= valuei <= 1e6
解法:
令d[i][j]表示前i天,使用了j次机会能获得的最大值,
由于i这一维很大,达到了1e9,但是events.length很小,因此需要先离散化一下(l,r,v)中的(l,r).

如果选择(i+1,r,v),那么d[i][j]可以转移到d[r][j+1],转移收益为v,
如果不选,那么d[i][j]可以转移到d[i+1][j].
dp一下就行了,有点01背包的意思.
code:
class Solution {
public:
    int maxValue(vector<vector<int>>& e, int k) {
        //离散化
        vector<int>temp;
        for(auto i:e){
            temp.push_back(i[0]);
            temp.push_back(i[1]);
        }
        sort(temp.begin(),temp.end());
        temp.resize(unique(temp.begin(),temp.end())-temp.begin());
        for(auto&i:e){
            i[0]=lower_bound(temp.begin(),temp.end(),i[0])-temp.begin()+1;
            i[1]=lower_bound(temp.begin(),temp.end(),i[1])-temp.begin()+1;
        }
        //桶排序
        vector<pair<int,int> >g[temp.size()+5];
        for(auto i:e){
            g[i[0]].push_back({i[1],i[2]});
        }
        //dp
        vector<vector<int>>d(temp.size()+5,vector<int>(k+5,0));
        for(int i=0;i<=temp.size();i++){
            for(int j=0;j<=k;j++){
                d[i+1][j]=max(d[i+1][j],d[i][j]);//不做
                if(j!=k){//做
                    for(auto p:g[i+1]){
                        int r=p.first,v=p.second;
                        d[r][j+1]=max(d[r][j+1],d[i][j]+v);
                    }
                }
            }
        }
        //out
        int ans=0;
        for(int i=0;i<=temp.size();i++){
            for(int j=0;j<=k;j++){
                ans=max(ans,d[i][j]);
            }
        }
        return ans;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值