2742. 给墙壁刷油漆
思路:方法一,记忆化搜索dfs。对于每一堵墙,都有两种状态,选和不选。
最后选择结果一定满足:所选墙的时间之和>=免费墙的个数。
在这个条件下,尽可能减少开销。细节看注释,时间复杂度0(n^2)
class Solution {
public:
int inf=5e8+10;//用于不满足条件时:即所选墙的时间之和<免费墙的个数
int v[550][1100];//存储遍历过的状态,第一维是墙的下标,第二维是:所选墙的时间之和“减去”免费墙的个数,这里1100,是因为它两之差中间可能存在负数,但是最大也不超过550
int dfs(int u,int res,vector<int>& cost, vector<int>& time){
//当res>u时,也就是剩下的都可以通过免费来实现
if(res>u) return 0;
//遍历完了,还是没有达到res>u的要求,返回不可能
if(u==-1) return inf;
//查看是否经历过这个状态,+550的原因就是因为res会存在负数
if(v[u][res+550]!=-1) return v[u][res+550];
//然后就是比较选与不选的最优值。
return v[u][res+550]=min(dfs(u-1,res+time[u],cost,time)+cost[u],dfs(u-1,res-1,cost,time));
}
int paintWalls(vector<int>& cost, vector<int>& time) {
//先把状态都初始化为没有到达过
memset(v,-1,sizeof v);
//参数:墙的下标、所选墙的时间之和“减去”免费墙的个数、cost、time
return dfs(cost.size()-1,0,cost,time);
}
};
思路:方法二,动态规划dp。最后选择结果一定满足:
1、所选墙的时间之和>=免费墙的个数。
2、所选墙的个数+免费墙的个数=n
结合以上两个条件可以推出:所选墙的(时间+1)>=n,即:所有付费墙Time+付费墙的个数>=n。
可以理解为0-1背包问题,即在n个墙里面,选出的m个墙,这m个墙的时间time之和,再加上m要>=n,同时支持最小。细节看注释,时间复杂度0(n^2)
class Solution {
public:
int paintWalls(vector<int>& cost, vector<int>& time) {
int n=cost.size();
//初始化状态
vector<int> dp(n+1,500000010);
dp[0]=0;
// 0-1背包问题
for(int i=0;i<cost.size();i++){
for(int j=n;j>0;j--){
dp[j]=min(dp[j],dp[max(0,j-(time[i]+1))]+cost[i]);
}
}
return dp[n];
}
};