算法训练营day48_动态规划(3.16提前写)
198.打家劫舍
这道题踩了个大坑,如果数组长度为1,就nums[0]一个数,不能初始f[1],会越界(因为f[1]用到了nums[1]);
土方法_背包思维
刚开始想到的就是二维背包,01背包,数组值为重量,价值,j最大就是sum值;
- f(i,j)表示从前i个里取,重量不超过j的最大价值(价值不会超过j,因为每个物品重量==价值,最多只能放j重量的东西,价值最大等于j);输出的时候输出f(size()-1,sum)就行;
- 要么取,要么不取;f(i,j)=max(f(i-1,j),f(i-2,j-w[i])+w[i]);
- 从2开始循环,故要初始化0,1;
- 01背包的循环套路;
class Solution {
public:
int f[110][40010];
int rob(vector<int>& nums) {
if(nums.size()==1) return nums[0];
memset(f,0,sizeof f);
int sum=0;
for(int i=0;i<nums.size();i++) sum+=nums[i];
for(int i=0;i<=sum;i++){
f[0][i]=nums[0];
f[1][i]=max(nums[0],nums[1]);
}
for(int i=2;i<nums.size();i++){
for(int j=0;j<=sum;j++){
f[i][j]=f[i-1][j];
if(j>=nums[i]) f[i][j]=max(f[i][j],f[i-2][j-nums[i]]+nums[i]);
}
}
return f[nums.size()-1][sum];
}
};
正解_只需要一维
这道题对于重量没要求,所以与前面不同,这道题把重量这一维度直接去掉!
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) return nums[0];
vector<int> f(nums.size());
f[0]=nums[0];
f[1]=max(nums[0],nums[1]);
for(int i=2;i<nums.size();i++){
f[i]=max(f[i-1],f[i-2]+nums[i]);
}
return f[nums.size()-1];
}
};
213.打家劫舍II
围成一圈,关键在于如何解环,转化成一排!
围成一圈之后,与之前不同的地方在于,如果0选了,n-1就选不了了;
分成两种情况:
- 0选了,1,n-1不选,考虑(2,n-1)左闭右开;
- 0没选,考虑(1,n)左闭右开;
越界问题搞了我好久。。。左闭右开,有一个元素是l==r-1,如果l>r-1说明一个元素都没,如[2,2)就是一个元素都没;
class Solution {
public:
int dp(vector<int>& nums,int l,int r){
if(l>r-1) return 0;
if(l==r-1) return nums[l];
vector<int> f(nums.size());
f[l]=nums[l];
f[l+1]=max(nums[l],nums[l+1]);
for(int i=l+2;i<r;i++){
f[i]=max(f[i-1],f[i-2]+nums[i]);
}
return f[r-1];
}
int rob(vector<int>& nums) {
int n=nums.size();
if (n==1) return nums[0];
return max(nums[0]+dp(nums,2,n-1),dp(nums,1,n));
}
};
337.打家劫舍III
树形dp,跟没有上司的舞会基本一样;只不过这里是链表构成的树形结构,平时我习惯数组构成树形结构;
这里的节点是T*,舞会节点是数字,这里节点值是t->val,舞会值是数组w[i];
下标是T*类型,故要开个哈希,f表示没偷,g表示偷了,也可以二维map,我这里不知道咋用哇(OK,查了一下, 就是map套map)
class Solution {
public:
unordered_map<TreeNode*,map<int,int>> f;
void dfs(TreeNode* t){
f[t][1]=t->val;
if(t->left!=NULL){
dfs(t->left);
f[t][0]+=max(f[t->left][0],f[t->left][1]);
f[t][1]+=f[t->left][0];
}
if(t->right!=NULL){
dfs(t->right);
f[t][0]+=max(f[t->right][0],f[t->right][1]);
f[t][1]+=f[t->right][0];
}
}
int rob(TreeNode* root) {
dfs(root);
return max(f[root][0],f[root][1]);
}
};