携带研究材料
题目
限制条件是背包的空间,目标是实现价值最大。输出是最大价值。研究材料的种类是含有映射关系数组的长度。
初始思路
1.找到比行李箱空间小的所有的材料;这是一个含有映射关系的数组
2.对该数组做空间小于给定空间的所有组合,并记录价值总和;这是个组合问题
3.找出价值最大的组合。
组合问题包含回溯过程,且按下不表。
DP的思路
1.DP[i][j]表示在容量为j的背包里放(0,i)物品的最大价值。
2.递推:因为dp[i][j]表示的是问题的解,即达到的最大价值。这是一个动态的过程,包含的不确定是每一件物品都有可能放进去或者没放进去。无论如何,上一个状态一定是dp[i-1][j],如果没放物品: dp[i][j]=dp[i-1][j];如果放入物品:dp[i][j]=dp[i-1][j-weight[i]]+value[i];
3.数组初始化:dp[i][j]代表问题的解,往里面放东西是容量固定,即一件一件放,是列。
dp[0][0]=0;dp[0,1]=?取决于第0件物品的weight有没有超过背包的容量,如果没超过,那么dp[0,1]=value[0],如果放不下,dp[0,1]=0;
dp[1,0]=0;dp[i,0]=0;
4.遍历序:
5.DP数组举例:
5,4
2 1 6 4 8
2 2 3 2 2
输出:
0 0 2 2 2
0 2 2 4 4
0 2 2 4 4
0 2 2 4 4
其中,weight.size就是n;
DP和贪心
贪心放远一点看当前的状态与过往的状态联系并不十分密切;买柠檬水收钱,后面的状态你总是有钱找的,前面的状态不一定会影响当前的状态。
DP则是一种累加效应,放进去就一定占地方。每一个状态都会影响后来的状态。
背包一维解法
#include<iostream>
#include<bits/stdc++.h>
#include<vector>
using namespace std;
int main(){
int n,bagweight;
cin>>n>>bagweight;
vector<int> weight(n,0);
vector<int> value(n,0);
for(int i=0;i<n;i++){
cin>>weight[i];
}
for(int j=0;j<n;j++){
cin>>value[j];
}
vector<int> dp(bagweight+1,0);
//初始化
for(int j=weight[0];j<=bagweight;j++){
dp[j]=value[0];
}
//递推条件
for(int i=1;i<n;i++){
for(int j=bagweight;j>=weight[i];j--){
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
cout<<dp[j]<<endl;
}
}
cout<<dp[bagweight]<<endl;
return 0;
}
分割等和子集
似曾相识,求一个数组中和为固定值的组合。
浙公网安备 33010602011771号