0/1背包最重要的是状态转移方程 ;
#include<iostream>
#include<cmath>
using namespace std;
int V,N;//N是物品的个数,V 是所容纳最大的体积
int v[1005],c[1005];
int dp[1005][1005];
int main(){
cin>>N>>V;
for(int i=1;i<=N;i++)cin>>v[i]>>c[i];
for(int i=1;i<=N;++i){
for(int j=1;j<=V;++j){
if(j<v[i])dp[i][j]=dp[i-1][j];
else dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+c[i]);
}
}for(int i=0;i<=N;++i){
for(int j=0;j<=V;++j){
cout<<dp[i][j]<<" ";
}cout<<"\n";
}
return 0;
}
通常状态转移方程分为拿和不拿两个状态;
如果j<v[i];表示不能够拿,则不能拿,则当前的dp值是不拿该物品所对应的dp值
如果j>=v[i]; 则取拿和不拿两个状态所对应的最大值;
通过打表找规律
0/1背包问题的优化;
#include<iostream>
#include<cmath>
using namespace std;
int V,N;//N是物品的个数,V 是所容纳最大的体积
int v[1005],c[1005];
int dp[1005];
int main(){
cin>>N>>V;
for(int i=1;i<=N;i++)cin>>v[i]>>c[i];
for(int i=1;i<=N;++i){
for(int j=V;j>=1;j--){
if(j>=v[i]) dp[j]=max(dp[j],dp[j-v[i]]+c[i]);
}
}cout<<dp[V];
return 0;
}
背包剩余容量从最大最开始推,不然覆盖掉前面的会影响后面的;
后无效应原则:当前状态只与上一个状态有关,与上上一个状态无关;