2830. 销售利润最大化
1. 题目描述
给你一个整数 n 表示数轴上的房屋数量,编号从 0 到 n - 1 。
另给你一个二维整数数组 offers ,其中 offers[i] = [starti, endi, goldi] 表示第 i 个买家想要以 goldi 枚金币的价格购买从 starti 到 endi 的所有房屋。
作为一名销售,你需要有策略地选择并销售房屋使自己的收入最大化。
返回你可以赚取的金币的最大数目。
注意 同一所房屋不能卖给不同的买家,并且允许保留一些房屋不进行出售。
2. 思路
DP+排序+二分
2.1. DP思路
DP两大思考方向:
- 选或不选(遍历到某个offer时选择卖或者不卖)
- 枚举(如果卖,枚举之前的offer,选出与当前offer不冲突的offer)
首先将offers
按end(题中的offers[][1])
从小到大排序
dp[i]
代表总共有i
个offer
时,收入的最大值。dp[n-1]
即为题目所求
状态方程:dp[i] = max{dp[i-1], dp[j]+offers[i][2]} , j满足0<=j<i,且offers[j][1]<offers[i][0]
dp[i-1]
是指不卖第i
个offer
中所包含范围内的房子,dp[j]+offers[i][2]
是指卖第i
个offer
中所包含范围内的房子,但要找到不冲突的offer
。offers[j][1]<offers[i][0]
是冲突判断。
因为dp[i-1]
一定比dp[i]
小或者相等,所以只需寻找满足offers[j][1]<offers[i][0]
的最大下标j
即可
伪代码:
int maximizeTheProfit(int n, vector<vector<int>>& offers) {
sort(offers.begin(), offers.end(), cmp);
int dp[100010]={0};
dp[0] = offers[0][2];
for(int i=1;i<offers.size();i++){
在[0,i-1]范围内寻找不冲突的最大下标index
dp[i] = max(dp[i-1], offers[i][2]+dp[index]);
}
return dp[offers.size()-1];
}
2.2 二分优化
寻找满足offers[j][1]<offers[i][0]
的最大下标j
先用二分寻找第一个满足offers[j][1]>=offers[i][0]
的下标j
,那么j-1
即时所求
二分代码:
int binarySearch(vector<vector<int>>& x, int target, int l, int r) {
// 找大于等于target的第一个数
while(l<=r){
int mid = (l+r)/2;
if(x[mid][1]<target){
l=mid+1;
}else{
r=mid-1;
}
}
return l;
}
2.3 c++ upper_bound/lower_bound使用(重点学习)
3. 代码
class Solution {
public:
static bool cmp(vector<int>& x,vector<int>& y) {
if(x[1] == y[1])return x[0] < y[0];
return x[1] < y[1];
}
int binarySearch(vector<vector<int>>& x, int target, int l, int r) {
// 找大于等于target的第一个数
while(l<=r){
int mid = (l+r)/2;
if(x[mid][1]<target){
l=mid+1;
}else{
r=mid-1;
}
}
return l;
}
int maximizeTheProfit(int n, vector<vector<int>>& offers) {
sort(offers.begin(), offers.end(), cmp);
int dp[100010]={0};
dp[0] = offers[0][2];
for(int i=1;i<offers.size();i++){
int index = binarySearch(offers, offers[i][0], 0, i-1);
index--; // index offers[j][1]小于offers[i][0]的最大下标
int tmp = index!=-1?dp[index]:0;
dp[i] = max(dp[i-1], offers[i][2]+tmp);
printf("index:%d dp[i]:%d\n", index, dp[i]);
}
return dp[offers.size()-1];
}
};
4. 同类型题
lc1235. 规划兼职工作
lc2008. 出租车的最大盈利