动态规划求解0/1背包问题

问题描述:

        典型的0/1背包问题,使用动态规划进行求解

解决方案:

        动态规划通常意义上是使用上一步的结果对这一步进行判决,因此需要构建的是一个能够对物品i(1=<i<=n)选取与上一步进行关联。在这里使用这种数据结构的目的是为了进行最优子策略的关联。

对于dp背包的物品的选择是1,背包剩余容量满足的时候,但是其价值的大小小于不装入的情况,这里就不进行物品的装入,但是相反的情况下就会满足需求这里的该步骤的最优策略是这一个物品的价值加上上一个物品的价值得到的局部最优的结果。还有一种情况是背包的剩余的容量无法装入物品,则这一个物品的最优价值就等于上一步该容量下的价值,即没有物品装入背包中。

        程序的编写是数据结构+算法。这里要想使用动态规划的算法的话,确定的数据结构是对于构建0/1背包关于最优价值和剩余容量的二维数组。

       

#include<stdio.h>
#include<malloc.h>
//问题描述:使用动态规划算法求解0/1背包问题,使每一步的决策和上一步进行关联 
#define MAXN 20
#define MAXW 100
int n=5, W=10;
int v[MAXN]={0,6,3,5,4,6};
int w[MAXN]={0,2,2,6,5,4};
int dp[MAXN][MAXW];
int x[MAXN];
int maxv=0;
void knap(){
	int i, j;
	for(i=0; i<=n; i++){
		dp[i][0]=0;
	}
	for(i=0; i<=W; i++){
		dp[i][0]=0;
	}
	for(i=1; i<=n; i++){
		for(j=1; j<=W; j++){
			if(j<w[i])
				dp[i][j]=dp[i-1][j];
			else{
				if(dp[i-1][j]>=(dp[i-1][j-w[i]]+v[i])){
					dp[i][j]=dp[i-1][j];
				}else{
					dp[i][j]=dp[i-1][j-w[i]]+v[i];
				}
			}
		} 
	}
}
void buildx(){
	int i, weight=W;
	for(i=n; i>=1; i--){
		if(dp[i][weight]==dp[i-1][weight]){
			x[i]=0;
		}else{
			x[i]=1;
			maxv+=v[i];
			weight=weight-w[i];	
		}
	}
} 
int main(){
	int i;
	knap();
	buildx();
//	printf("%d", x[0]);
	for(i=1; i<=n; i++){
		if(x[i]==1){
			printf("选择了%d\n", i); 
		}
	}
	printf("物品的总价值:%d", maxv);
	return 0;
} 

knap()是构建dp数组的过程,buildx()是找到最优解的x数组的过程,这里的选择了该物品的话,则这一层的最优价值必不等于上个物品该剩余容量下的最优价值,从这里进行判断是否选择了该物品。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个采用动态规划求解0/1背包问题的C语言实现: ```c #include <stdio.h> #include <stdlib.h> #define MAX_N 100 // 物品数量最大值 #define MAX_W 1000 // 背包容量最大值 int N; // 物品数量 int W; // 背包容量 int w[MAX_N]; // 各个物品的重量 int v[MAX_N]; // 各个物品的价值 int dp[MAX_N+1][MAX_W+1]; // 动态规划数组 // 求解0/1背包问题 int solve() { int i, j; for (i = 0; i <= N; i++) { for (j = 0; j <= W; j++) { if (i == 0 || j == 0) { // 边界条件,当物品数量为0或背包容量为0时,价值为0 dp[i][j] = 0; } else if (j < w[i-1]) { // 当前物品放不下时,价值与前一个相同 dp[i][j] = dp[i-1][j]; } else { // 当前物品可放下时,取放和不放中价值最大的一个 dp[i][j] = (dp[i-1][j-w[i-1]]+v[i-1] > dp[i-1][j]) ? dp[i-1][j-w[i-1]]+v[i-1] : dp[i-1][j]; } } } return dp[N][W]; } int main() { int i; printf("请输入物品数量和背包容量:\n"); scanf("%d%d", &N, &W); printf("请输入各个物品的重量:\n"); for (i = 0; i < N; i++) { scanf("%d", &w[i]); } printf("请输入各个物品的价值:\n"); for (i = 0; i < N; i++) { scanf("%d", &v[i]); } printf("最大价值为:%d\n", solve()); return 0; } ``` 该实现中,动态规划数组 `dp[N+1][W+1]` 表示在前 N 个物品、背包容量为 W 的情况下,可获得的最大价值。通过两层循环,遍历所有情况,并填充动态规划数组,最后返回 `dp[N][W]` 即可得到最大价值。具体实现可参考注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值