选择背包问题详细求解:
1.当包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);V(i,j)表示前i个物品种类装入容量为j的背包产生的最大价值。
2.还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }
3.其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i)但价值增加了v(i);
状态转移方程:
过程举例:
m【i】【j】表示该二维表格,将m【i】【0】和m【0】【j】初始化为0(背包空间为0和前0种物品都会导致产生的价值为0.之后每个m【i】【j】的值都是比较该物品的重量和当前背包容量,如不能放进去则V(i,j)=V(i-1,j);否则还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }
代码参考:
#include <iostream> #include <cstring> #include <iomanip> #include<fstream> using namespace std; const int N=15; int main() { int n=0,c=0; ifstream in("input.txt"); ofstream out("output.txt"); in>>n; in>>c; int v[N]={0}; int w[N]={0}; for(int i=1;i<=n;i++) in>>v[i]; for(int i=1;i<=n;i++) in>>w[i]; int m[N][N];
memset(m,0,sizeof(m)); for(int i=1;i<=n;i++) { for(int j=1;j<=c;j++) { if(j>=w[i]) m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]); else m[i][j]=m[i-1][j]; } } // for(int i=0;i<=n;i++) // { // for(int j=0;j<=c;j++) // { // cout<<setw(2) <<m[i][j]<<' '; // } // cout<<endl; // } int j=c, b[n]; for(int i=n;i>0;i--) { if(m[i][j]==m[i-1][j]) { b[i]=0;
}
else { b[i]=1; j=j-w[i]; } } out<<setw(2) <<m[n][c]<<endl; for(int i=1;i<=n;i++) { out<<b[i]<<" "; }
return 0; } |