动态规划算法思想:设m[i][j]用来表示从前i项物品中区取出装入体积为j的背包的物品的最大价值。
其中i的范围为0到n,其中j的范围为0到c,程序要寻求的解为m[n][c]。可以分以下三种情况:
①m[0][j]对所有的j的值为0(物品种类为0), m[i][0]对所有的i的值为0(体积为0)
②当前的体积j大于等于w[i]时, m[i][j]是下面两个量的最大值:m[i-1][j](不装)和 m[i-1][j-w[i-1]]+v[i](装)
③当前的体积j小于w[i]时,m[i][j]等于m[i-1][j]
(0 1背包 滚动数组)
#include<iostream> using namespace std; const int N=13000; //w[N]表示物品的重量,v[N]表示物品的价值 c表示总容量 int w[N],v[N],m[N],c,n; int main() { int i,j; while(cin>>n>>c){ for(i=0;i<n;i++) cin>>w[i]>>v[i]; memset(m,0,sizeof(m)); for(i=0;i<n;i++) for(j=c;j>=0;j--){ if(j>=w[i]) m[j]=max(m[j],m[j-w[i]]+v[i]);//滚动数组 } cout<<m[c]<<endl; } return 0; }
m数组是从上到下,从右往左计算的。在计算m(i,j)之前,m[j]里保存的就是是m(i-1,j)的值,
而m[j-w]里保存的是m(i-1,j-w)而不是m(i,j-w) --别忘了j是逆序枚举的,此时m(i,j-w)还没有出来。这样,m[j]>?m[j-w]+v实际是把max{f(i-1),f(i-1,j-w)}保存在m[j]中,覆盖掉m[j]原来的m(i-1,j).
采药(0 1背包):http://tyvj.cn/Problem_Show.asp?id=1005
#include<iostream> using namespace std; const int N=1005; //w[N]表示物品的重量,v[N]表示物品的价值 int w[N],v[N],m[N][N],t,n; int main() { int i,j; cin>>t>>n; for(i=0;i<n;i++) cin>>w[i]>>v[i]; for(i=1;i<=n;i++) for(j=1;j<=t;j++){ m[i][j]=m[i-1][j]; if(j>=w[i-1]) m[i][j]=max(m[i-1][j],m[i-1][j-w[i-1]]+v[i-1]); } cout<<m[n][t]<<endl; //system("pause"); return 0; }
#include<iostream> #include<cstring> using namespace std; const int N=20005; int c,n,w[35],v[35],m[N]={0}; int main() { cin>>c>>n; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=n;i++) for(int j=c;j>=w[i];j--){ m[j]=max(m[j],m[j-w[i]]+w[i]); //cout<<m[j]<<endl; } cout<<c-m[c]<<endl; return 0; }