动态规划---01背包问题(2种方法)

一、动态规划
代表一类问题(最优子结构或子问题最优性)的一般解法,是设计方法或者策略,不是具体算法
本质:递推,核心是找到状态转移的方式,写出dp方程。
解决问题:交叉,重叠子问题(最优子问题)
形式:
记忆型递归
递推
与深搜的区别:深搜要所有符合条件的解,动态规划要求最优解(唯一解)
二、题目
有n个重量和价值分别为wi和vi的物品,从这些物品中挑选出重量不超过w的物品,求所有挑选方案中价值总和的最大值。
1<=n<=100
1<=wi,vi<=100
1<=w<<10000
输入:
n=4
(w,v)={(2,3),(1,2),(3,4),(2,3)}
w=5
输出
7(选择第0,1,3号物品)


分析思路

  • 方法一:递推

因为对每个物品只有选和不选两种情况,所以这个问题称为01背包问题。
两个决定性量,重量,价值,
物品只有两种选择拿或者不拿,在重量限定的条件下,使得价值达到最大
与深搜的区别,深搜要所有符合条件的解,动态规划要求最优解
用深搜进行分析,找一个卡点,找到之后只能从卡点开始往后选
在这里插入图片描述

  • 代码:

public class Bag01 {
	static int[] w= {2,1,3,2}; //重量表
	static int[] v= {3,2,4,2};  //价值表
	static int n=4; //物品数量
	static int W=5; //背包的承重极限
	static int max(int a,int b) {
		return a;
	
	}
	public static void main(String[] args) {
		int ww=W;
		int ans=dfs(0,ww);  //从第一个物品开始
		System.out.println(ans);
	}
	static int dfs(int i,int ww) {
		//出口条件
		if(ww<=0) return 0;  //装不进去
		if(i==n) return 0;  //没东西可选了
		int v2=dfs(i+1,ww);  //不选择当前物品
		if(ww>=w[i]) {
			int v1=v[i]+dfs(i+1,ww-w[i]);  //选择当前物品
			return max(v1,v2);
		}
		else {
			return v2;
		}
	}
}

在这里插入图片描述

  • 方法二:记忆型递归(处理重叠子问题)
    二叉树:递归自下往上推
    在这里插入图片描述
    括号前缀代表层数和从第几个物品开始选,开始选的编号越小所选的范围越大
    记忆:把f(3,2)这样重叠的问题记忆下来
    f(x,y)采用二维数组
    x:长度n,物品数量[0,n-1]
    y:总重量 开辟到w+1
    二维数组第n行第m列
    把二维数组都填为-1

记忆递归:
1.计算前查询
2.计算后保存

  • 代码

import java.util.Arrays;

public class Bag01jiyi {
	static int[] w= {2,1,3,2}; //重量表
	static int[] v= {3,2,4,2};  //价值表
	static int n=4; //物品数量
	static int W=5; //背包的承重极限
	static int max(int a,int b) {
		return a;
	}
	public static void main(String[] args) {
		int ww=W;
		int ans=m(0,ww);  //从第一个物品开始
		System.out.println(ans);
		rec=new int[n][W+1];  //二维数组存放
		for(int i=0;i<n;i++) {
			Arrays.fill(rec[i], -1);  //重量最小为0
		}
		ww=W;
		ans=m(0,ww);
		System.out.println(ans);
	}
	static int[][] rec;
	static int m(int i,int ww) {
		//出口条件
		if(ww<=0) return 0;
		if(i==n) return 0;
		//就算之前先查询
		if(rec[i][ww]>=0)
			return rec[i][ww];
		int v2=m(i+1,ww);  //不选择当前物品
		int ans;
		if(ww>=w[i]) {
			int v1=v[i]+m(i+1,ww-w[i]);  //选择当前物品
			ans=max(v1,v2);
		}
		else {
			ans=v2;
		}
		//计算之后做保存
		rec[i][ww]=ans;
		return ans;
	}
}

在这里插入图片描述

发布了137 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/gl620321/article/details/105605590