c[i][w]表示背包容量为w时,i个物品导致的最优解的总价值。递归定义如下
0 i=0或w=0
c[]i[w]= c[i-1][w] wi>w
max{c[i-1][w-wi]+v,c[i-1][w]} i>0且wi<=w
此时时间复杂度和空间复杂度均为O(VN),时间复杂度已不能优化,但空间复杂度还能够优化到O。即把二维数组用一维数组来解。但此时要顺序逆推。
#include <stdio.h>
extern int c[6][18]={};
extern int w[6]={0,3,4,7,8,9};
extern int v[6]={0,4,5,10,11,13};
extern int x[6]={0};
void package(int n,int W)
{
for(int i=1;i<=W;i++)
printf("%3d",i);
puts(" ");
for(int i=1;i<=n;i++)
{
c[i][0]=0;
for(int j=1;j<=W;j++)
{
if(w[i]<=j)
{
if(v[i]+c[i-1][j-w[i]]>c[i-1][j])
{
c[i][j]=v[i]+c[i-1][j-w[i]];
}
else
{
c[i][j]=c[i-1][j];
}
}
else
{
c[i][j]=c[i-1][j];
}
printf("%3d",c[i][j]);
}
puts("");
}
for(int i=n;i>=2;i--)
{
if(c[i][W]==c[i-1][W])
{
x[i]=0;//即此时没有吧第i件物品放入背包中
}
else
{
x[i]=1;//如果x[i]等于1表示被选中
W -= w[i];
}
x[1]=c[1][W] ? 1:0;
}
for(int i=1;i<=n;i++)
{
printf("%3d",x[i]);
}
puts("");
}
int main()
{
package(5,17);
system("pause");
return 0;
}
下面是用一维数组解背包问题。
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
vector<int> value;
vector<int> volume;
vector<int> DP;
int N,V;
while ( cin >> N >> V )
{
value.resize(N+1);
volume.resize(V+1);
DP.clear();
DP.resize(V+1);
for ( int i = 1; i <= N; i++ )
{
cin >> volume[i] >> value[i];
}
for ( int v = V; v >= 1; v-- )
{
printf("%3d",v);
}
cout<<endl;
for ( int i = 1; i <= N; i++ )
{
for ( int v = V; v >= 1; v-- )
{
if ( v >= volume[i] )
{
if ( DP[v-volume[i]] + value[i] >= DP[v] )
{
DP[v] = DP[v-volume[i]] + value[i];
}
}
printf("%3d",DP[v]);
}
cout<<endl;
}
cout << DP[V] << endl;
}
return 0;
}