一个简单的0-1背包问题(2)

还是上次的问题,从N个数字(N较大)从取出随意m个数字(m不定)相加,得到最接近一个常数c的组合,原来用无穷列举的方法解出来,时间复杂度上为O(2^n),对于n比较大的情况,几乎为无解,重新设计了算法,用动态规划的方法实现,时间复杂度为nc,同样能够得到最优解,但是所花费的时间大大减小,唯一不爽的是,要求数组都是int类型,c也一样,如果是double类型的话,为了精度,需要开销的空间太大,我的老爷机没法继续实现,所以没有做double数组的算法,如果大家有兴趣,可以继续写下去
void MyAlogorithms::Knapsack(int w[],int c,int n,int **f)
{

	for (int y=0;y<=w[n-1];y++)
		f[n-1][y]=0;
	for (int y=w[n-1];y<c-1;y++)
		f[n-1][y]=w[n-1];

	for (int i=n-2;i>=0;i--)
	{
		for (int y=0;y<=w[i];y++)
			f[i][y]=f[i+1][y];
		for (int y=w[i];y<c-1;y++)
			f[i][y]=max(f[i+1][y],f[i+1][y-w[i]]+w[i]);
	
	}
	f[0][c-1]=f[1][c-1];
	if (c>=w[0])
	{
		f[0][c-1]=max(f[1][c-1],f[2][c-1-w[0]]+w[0]);
		
	}
}

void MyAlogorithms::Traceback(int **f,int w[],int c,int n,int x[])
{
	for (int i=0;i<n-1;i++)
	{
		if (f[i][c-1]==f[i+1][c-1])
		{
			x[i]=0;
		} 
		else
		{
			x[i]=1;
			c=c-w[i];
		}
	}
	x[n-1]=(f[n-1][c-1])?1:0;
}

测试

#include <iostream>
#include <fstream>
#include "MyAlgorithms.h"

using namespace std;

const int N=99;
const int tarnum=412645;

int main()
{
	int i=0;
	int sum=0;
	int s[N];
	ifstream in;
	in.open("shuzi.txt");
	if (!in.is_open())
	{
		cout<<"Can't open the file";
		exit(EXIT_FAILURE);
	}
	in>>s[i];
	while(in.good())
	{
		i++;
		in>>s[i];
	}
	
	MyAlogorithms ma;
	int **f=new int*[N];
	for (int k=0;k<N;k++)
	{
		f[k]=new int[tarnum];
	}
	int b[N]={0};
        ma.Knapsack(s,tarnum,N,f);
	
	ma.Traceback(f,s,tarnum,N,b);

	for (int k=0;k<N;k++)
	{
		sum=sum+b[k]*s[k];
		if (1==b[k])
		{
			cout<<s[k]<<endl;
		}
		
	}

	cout<<sum<<endl;

	for(int k=0;k<N;k++)
		delete []f[k];
	delete []f;

	system("Pause");


}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值