对01背包问题进行分析

文章目录

  • 前言
  • 一、什么是01背包问题?
  • 二、解决方法
    • 1.动态规划法
    • 2.回溯法
  • 总结


前言

背包问题是算法学习的经典问题,背包问题又在不同的问题条件下可以用到不同的算法,如0-1背包,完全背包(硬币找零 硬币数无限制),多重背包(硬币找零 硬币数有限制),分数背包等。我们可以通过不同的背包问题来学习算法,本文章主要探讨01背包问题的求解方法。


一、什么是01背包问题?

问题描述:给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包最大承载重量为C。物品是不可分割的,应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

二、解决方法

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N=10;
const int bag=N*2;
const int MAXSIZE=100000;
struct goods{
	int w;//重量
	int v;//价值
}g[N];
int max_value=0;
int count=0;
int a[N],r[N+1],dp[N][bag+1],x[N];
int main()
{
	int i,start,end;
	for(i=0;i<N;i++){
		g[i].v=rand()%5+1;
		g[i].w=rand()%5+1;
		printf("物品%d,价值%d,重量%d\n",i,g[i].v,g[i].w);
	}
	r[N]=0;
	for(i=N-1;i>=0;i--){
		r[i]=r[i+1]+g[i].v;
	}
	printf("回溯能获得的最大价值为:%d\n",huisu(0,0,0));
	printf("找到一种最佳方案:");huisuxunzhao();printf("\n");
	printf("动态规划能获得的最大价值为:%d\n",guihua());
	printf("找到一种最佳方案:");guihuaxunzhao();printf("\n");
	return 0;
}

1.动态规划法

代码如下(示例):

int guihua()
{
	for(int i=0;i<N;i++)
		for(int j=0;j<=bag;j++){
			if(i==0&&g[i].w>j)
				dp[i][j]=0;
			else if(i==0&&g[i].w<=j)
				dp[i][j]=g[i].v;
			else if(j==0)
				dp[i][j]=0;
			else if(g[i].w>j)
				dp[i][j]=dp[i-1][j];
			else
				dp[i][j]=dp[i-1][j]>(dp[i-1][j-g[i].w]+g[i].v)?dp[i-1][j]:(dp[i-1][j-g[i].w]+g[i].v);
		}
	return dp[N-1][bag];
}
void guihuaxunzhao()
{
	int i=N-1,j=bag;
	while(1){
		if(i>0){
			if(dp[i-1][j]<(dp[i-1][j-g[i].w]+g[i].v)){
				printf("%d ",i);
				j=j-g[i].w;
				i--;
			}
			else{
				i--;
				}
		}
		else if(i==0){
			if(j>=g[i].w){
				printf("%d ",i);
				break;
			}
			else
				break;
		}
	}
}

2.回溯法

代码如下(示例):

int huisu(int t,int now_v,int now_w)
{
	if(t==N){
		if(now_w<=bag&&now_v>max_value){
			max_value=now_v;
			for(int j=0;j<N;j++){
				x[j]=a[j];
			}
		}
    }
    else{
        for(int i=0;i<=1;i++){
            a[t]=i;
			now_v=now_v+g[t].v*i;
			now_w=now_w+g[t].w*i;
			if(now_w<=bag&&now_v+r[t+1]>=max_value)
				huisu(t+1,now_v,now_w);
        }
    }
	return max_value;
}
void huisuxunzhao()
{
	int w=0;
	for(int i=N-1;i>=0;i--){
		if(x[i]==1){
			printf("%d ",i);
		}
	}
}

总结

以上就是解决01背包问题的两种方法,01背包还可以用分支限界法解决,读者可以自己思考。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

災變廢土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值