0-1背包动态规划的优化过程

1用动态规划写出0-1背包问题的解法

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N=30;//全局变量,物品数量
const int bag=N;//全局变量,背包承重量
int max_value=0;//全局变量,记录能获得的最大价值
int a[N],v[N],w[N],r[N+1];//全局变量,分别保存0-1方案,物品价值,物品重量,剩余总价值
int max(int a,int b);
int fa[N]={0};
int backpack(int i,int m)//i为第i个物品,m为有m元钱 
{
	    if(i == 0) return 0;//边界
    if(w[i]>m) 
	return  backpack(i-1,m);    //当这个物品装不下时 就不需要比较了
    else
		return max(backpack(i-1, m),backpack(i-1, m - w[i])+v[i]);
} 

int main()
{
	int i,start,end;
	printf("背包最大承重%d公斤\n",bag);
	for(i=0;i<N;i++)//随机生成价值和重量范围1-5
	{
		v[i]=rand()%5+1;
		w[i]=rand()%5+1;
		printf("物品%d,价值%d,重量%d\n",i,v[i],w[i]);
	}
	r[N]=0;
	start=clock();
	printf("能获得的最大价值为:%d\n",backpack(N,bag));
	end=clock();
	printf("耗时:%dms\n",end-start);
	return 0;
}
int max(int a,int b)
{
if(a>b) return a;
else return b;
}

 动态规划的部分主要就是这个函数

int backpack(int i,int m)//i为第i个物品,m为有m元钱 
{
	    if(i == 0) return 0;//边界
    if(w[i]>m) 
	return  backpack(i-1,m);    //当这个物品装不下时 就不需要比较了
    else
		return max(backpack(i-1, m),backpack(i-1, m - w[i])+v[i]);
} 

可以看出这个代码时间复杂度是很高的,因为他有很多节点重复计算了

我们可以通过加记忆数组的方式进行优化使其算法复杂度降到O(n*N)。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N=1000;//全局变量,物品数量
const int bag=N;//全局变量,背包承重量
int max_value=0;//全局变量,记录能获得的最大价值
int a[N],v[N],w[N],r[N+1];//全局变量,分别保存0-1方案,物品价值,物品重量,剩余总价值
int max(int a,int b);
int fa[N]={0};
int jy[1000][1000]={0};//记忆数组 
int backpack(int i,int m)//i为第i个物品,m为有m元钱 
{
	if(i == 0) return 0;//边界
	if(jy[i][m]>0)return jy[i][m]; 
    if(w[i]>m) 
		return jy[i][m]=backpack(i-1,m);//当这个物品装不下时 就不需要比较了
    else
		jy[i][m]=max(backpack(i-1,m),backpack(i-1, m - w[i])+v[i]);
	return jy[i][m];
} 

int main()
{
	int i,start,end;
	printf("背包最大承重%d公斤\n",bag);
	for(i=0;i<N;i++)//随机生成价值和重量范围1-5
	{
		v[i]=rand()%5+1;
		w[i]=rand()%5+1;
		printf("物品%d,价值%d,重量%d\n",i,v[i],w[i]);
	}
	r[N]=0;
	start=clock();
	printf("能获得的最大价值为:%d\n",backpack(N,bag));
	end=clock();
	printf("耗时:%dms\n",end-start);
	return 0;
}
int max(int a,int b)
{
if(a>b) return a;
else return b;
}

当然,还能将其写成递推的形式

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N=1000;//全局变量,物品数量
const int bag=N;//全局变量,背包承重量
int max_value=0;//全局变量,记录能获得的最大价值
int a[N],v[N],w[N],r[N+1];//全局变量,分别保存0-1方案,物品价值,物品重量,剩余总价值
int dp[N][bag+1]={0},fa[N]={0};
int max(int a,int b);
void Find(int N,int bag);
int backpack()
{
	for(int i=1;i<N;i++)
	{	
		for(int j=1;j<=bag;j++)
		{
			if(w[i]>j)
				dp[i][j]=dp[i-1][j];
			else
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
		}
		
	}
	return dp[N-1][bag];//返回最大价值
}
void Find(int i,int j)
{
	if(i==0)
	{
		for(int i=0;i<N;i++)
			printf("%d",fa[i]);
	}
	if(dp[i][j]==dp[i-1][j])
	{
		fa[i]=0;
		Find(i-1,j);
	}
	else if(dp[i][j]==dp[i-1][j-w[i]]+v[i])
	{
		fa[i]=1;
		Find(i-1,j-w[i]);
	}

}
int main()
{
	int i,start,end;
	printf("背包最大承重%d公斤\n",bag);
	for(i=0;i<N;i++)//随机生成价值和重量范围1-5
	{
		v[i]=rand()%5+1;
		w[i]=rand()%5+1;
		printf("物品%d,价值%d,重量%d\n",i,v[i],w[i]);
	}
	r[N]=0;
	start=clock();
	printf("能获得的最大价值为:%d\n",backpack());
	end=clock();
	Find(N-1,bag-1);
	printf("耗时:%dms\n",end-start);
	return 0;
}
int max(int a,int b)
{
if(a>b) return a;
else return b;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值