背包问题----动态规划

一、动态规划

动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。把问题分解成若干个子问题,然后记录下每个子问题的解,避免重复计算,再从众多子问题中选出最优解。
点击这查看上一篇动态规划详解

问题描述:给定 n 个重量为w1,w2···wn,价值为v1,v2···vn,背包的承重量为 W 。

背包问题是给定 W 重量的背包装入尽可能高价值的物品。F(i,w):前 i 个物品,当前背包还可以装w重量。

我们可以把前 i 个物品中放入重量为 W 的背包中价值最大化问题分解成两个问题:

  1. 装入背包的物品不包括第 i 个物品,F(i , w) = F(i -1 , w);
  2. 装入背包的物品包括第 i 个物品,F(i , w) = F(i -1 , w - wi) + vi;

现在假设有四个物品,重量分别为 2, 1, 3, 2; 价值为 12, 10, 20, 15; 给定一个承重为 W = 5 的背包,求装入物品的最大价值是多少?

在这里插入图片描述
首先,根据以上步骤,可以将问题分解为:

  1. F(4, 5) = max{F(3, 5), F(3, 3) + 15 };
  2. F(3, 5) = max{F(2, 5), F(2, 2) + 20 };
  3. F(3, 3) = max{F(2, 3), F(2, 0) + 20 };
  4. F(2, 5) = max{F(1, 5), F(1, 4) + 10 };
    .
    .
    .
  5. F(0, 5) = 0;
  6. F(i, 0) = 0;

同样的,我们需要定义一个二维数组来保存每一个子问题的解,避免重复计算。

在这里插入图片描述

代码如下:

public class Main{
	static int[] v = {12, 10, 20, 15};
	static int[] w = {2, 1, 3, 2};
	public static void main(String[] args){
	int W = 5;
	int[][] F = new int[v.length][W];
	Func(F, v.length-1, W-1);
	System.out.println(F[v.length-1][W-1]);
	}
	/**
	 * 递归三部曲:
	 * 1.确定参数与返回类型
	 * 2.确定终止条件
	 * 3.确定单体循环
	 * @param Ye
	 * @return
	 */
	public static int Func(int[][] F,int i,int W)
	{
		if(i < 0 || W < 0) return 0;
		if(F[i][W] != 0) return F[i][W];
		if((W-w[i]) >= -1)
			F[i][W] = Math.max(Func(F,i-1, W), Func(F,i-1, W-w[i]) + v[i]);
		else
			F[i][W] = Func(F,i-1, W);
		return F[i][W];
	}
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页