删除并获得点数
分析:
使用动态规划解决
这道题依旧是 打家劫舍I 问题的变型。
我们注意到题目描述,选择 x 数字的时候, x - 1 与 x + 1 是不能被选择的。像不像 打家劫舍 问题中,选择 i 位置的金额之后,就不能选择 i - 1 位置以及 i + 1 位置的金额。因此,我们可以创建一个大小为 N(根据题目的数据范围)的 hash 数组,将 nums 数组中每一个元素 x ,累加到 hash 数组下标为 x 的位置处,然后在 hash 数组上来一次 打家劫舍 即可。
代码:
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
int n=nums.size();
const int N=1e4+10;
int a[N]={0};
for(auto num:nums)
{
a[num]+=num;
}
vector<int>f(N+1);//选
vector<int>g(N+1);//不选
f[0]=a[0];
for(int i=1;i<=N;i++)
{
f[i]=g[i-1]+a[i-1];
g[i]=max(g[i-1],f[i-1]);
}
return max(f[N],g[N]);
}
};
粉刷房子
分析:
使用动态规划解决
状态表示:
这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求。定义一个状态表示:但是我们这个题在 i 位置的时候,会面临「红」「蓝」「绿」三种抉择,所依赖的状态需要细
分:
dp[i][0] 表示:粉刷到 i 位置的时候,最后一个位置粉刷上「红色」,此时的最小花
费;
dp[i][1] 表示:粉刷到 i 位置的时候,最后一个位置粉刷上「蓝色」,此时的最小花
费;
dp[i][2] 表示:粉刷到 i 位置的时候,最后一个位置粉刷上「绿色」,此时的最小花
费。
状态转移方程:
因为状态表示定义了三个,因此我们的状态转移方程也要分析三个:
对于 dp[i][0] :
如果第 i 个位置粉刷上「红色」,那么 i - 1 位置上可以是「蓝色」或者「绿色」。因此我们需要知道粉刷到 i - 1 位置上的时候,粉刷上「蓝色」或者「绿色」的最小花费,然后加上 i位置的花费即可。于是状态转移方程为: dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0] ;
同理,我们可以推导出另外两个状态转移方程为:
dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1] 。
dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2] 。
代码:
class Solution {
public:
int minCost(vector<vector<int>>& costs) {
int n=costs.size();
vector<vector<int>>dp(n+1,vector<int>(5));
for(int i=1;i<=n;i++)
{
dp[i][0]=min(dp[i-1][1],dp[i-1][2])+costs[i-1][0];
dp[i][1]=min(dp[i-1][0],dp[i-1][2])+costs[i-1][1];
dp[i][2]=min(dp[i-1][1],dp[i-1][0])+costs[i-1][2];
}
return min({dp[n][1],dp[n][0],dp[n][2]});
}
};