一.01背包状态转移方程解析:
原方程 f(i,j)=max(f(i-1,j),f(i-1,j-w[i])+c[i]))
1.f(i,j)表示前i件物品放到容积为j的背包中的最大价值,w[i]表示第i件物品的重量,c[i]表示第i件物品的价值
2.一件物品最多有两种选择:放入背包或不放
3.f(i-1,j)--------i-1表示第i件物品不放入背包,j表示将i不放进背包的容积,f(i-1,j)表示不放时的最大价值
4(1).f(i-1,j-w[i])+c[i]------------表示一定将物品放入背包,此时其他物品的最大价值是f(i-1,j-w[i])(即其他i-1件物品放入j-w[i]大的空间内的最大价值)
(2).其他物品最大价值+此物品的价值==放入时的最大价值
5.(放入物品则留给其他物品的空间就会变小,其他物品的总价值也会随之变化,所以并不是当放入物品时的总价值最大)
6.比较两种可能的最大价值即是f(i,j)状态的最大价值.即max(f(i-1,j),f(i-1,j-w[i])+c[i]))
7.这时如果放入物品,则一定将该物品放下,什么意思呢?当放入这件时,为保证该物品一定能放下,便可以用作差法为该物体腾出空间即可保证可以放入
二.01背包打表模拟:
【输入样例】 10 4 //背包容量与物品数量 2 1 //第1件物品的重量与价值 3 3 //第2件物品的重量与价值 4 5 //第3件物品的重量与价值 7 9 //第4件物品的重量与价值
打表模拟如下图:
三.代码及解析:
#include<bits/stdc++.h> using namespace std; int m,n; int w[500],c[500],a[500][500];//w为重量,c为价值,a数组为上图的f[i,j] int main() { cin>>m>>n; for(int i=1; i<=n; i++) { cin>>w[i]>>c[i]; a[0][i]=0;//将0件物品放入容量为i的包中 a[i][0]=0; //都放不下,总价为0 } //循环解析;前i件物品放入容量为j的背包 for(int i=1; i<=n; i++) //所有物品考虑放或不放 { for(int j=1; j<=m; j++) { if(j>=w[i])//可以放入时(一定放此物品) a[i][j]=max(a[i-1][j],a[i-1][j-w[i]]+c[i]); else//放不下 a[i][j]=a[i-1][j];//不放此物品的最大价值 } } cout<<a[n][m]; return 0; }
(蒟蒻见解,如有bug请指出[举手 双手赞成])