0-1背包问题(knapsack problem)

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值