动态规划--1基本知识点+01背包
2017-03-10 21:31
246 查看
1. 动态规划主要用在求解最优化问题上,与分治法类似,都是将原问题分解成多个子问题,递归求解子问题,在合并计算出最优解的过程。但是二者还是有区别的,主要区别:
(1)动态规划分解的子问题多是有互相联系性的,经分解的子问题往往不是彼此独立的;
(2)动态规划对每个子问题只求解一次,将结果保存到表中(动态规划具有多种格式,但它们具有相同的填表格式)从而避免了当子问题再次出现过程中重复求解,节省时间;
(3)动态规划实质上是一种空间换取时间的算法,它将子问题的结果存储下来避免重复计算,所以它比一般算法所占用的空间多。
(4)记忆搜索和动态规划方式类似,是一种递归调用算法,将计算过的结果保存下来,避免重复计算,但是动态规划的计算是按照一定顺序的,比如子问题b的计算需要子问题a的结果,那么先计算a再算b,记忆搜索没管这些,哪个先来先计算哪个,将其保存。
2.应用场景:
(1)具有最优子结构:问题的最优策略的子策略总是最优的;(2)子问题的重叠性:
3.步骤:描述最优解的结构,递归定义最优解,自底向上计算,合并最优解
4.典型问题:全路径最短路径的Floyd算法,0-1背包问题,矩阵链乘法,求数组中连续子串的最大和问题,最长公共子序列问题,找零钱问题
5.动态规划算法的运行时间多数情况下是两个因素的乘积:子问题的个数*每个子问题有多少种选择。比如在矩阵链相乘问题中总共有O(n^2)个子问题,每个子问题至多有n-1个选择,所以时间复杂度为O(n^3)
6.0-1背包问题
问题:n件物品,第i件物品值vi元 重wi磅(vi和wi是整数),小偷的背包最多只能装W磅,请问他该带走那几样东西?
思想:物品 j 除外剩余 n-1件物品,能带走的物品最多中 W-wj。A(j,W)表示前 j 件物品中选择最佳组合放到重为W的包中,对于物体 j,一种可能是它加入前面的物品一起放进包里,那么就是 A(j-1,W-wi)+vj 即前 j-1件物品放在中 W-wj的包里的最好效果+放入j的价值;另一种可能就是 j不放进包里 包里仍旧放前j-1中的物品 那么价值为A(j-1,W)
而A(0,W )=0 即没有物品只有包, A(j,0)=0有物品没有包。可以能到 :当 wj <W时 A(j,W)=Max( A(j-1,W-wi)+vj , A(j-1,W)) , 当wj>W时 A(j,W)= A(j-1,W)
eg:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
一个背包有一定的承重cap,有N件物品,每件都有自己的价值,记录在数组v中,也都有自己的重量,记录在数组w中,每件物品只能选择要装入背包还是不装入背包,要求在不超过背包承重的前提下,选出物品的总价值最大。
给定物品的重量w价值v及物品数n和承重cap。请返回最大总价值。
public class Backpack {
public int maxValue(int[] w, int[] v, int n, int cap) {
// write code here
int[] dp=new int[cap+1];//承重
for(int i=0;i<n;i++){
for(int j=cap;j>=w[i];j--){
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
return dp[cap];
}
}
(1)动态规划分解的子问题多是有互相联系性的,经分解的子问题往往不是彼此独立的;
(2)动态规划对每个子问题只求解一次,将结果保存到表中(动态规划具有多种格式,但它们具有相同的填表格式)从而避免了当子问题再次出现过程中重复求解,节省时间;
(3)动态规划实质上是一种空间换取时间的算法,它将子问题的结果存储下来避免重复计算,所以它比一般算法所占用的空间多。
(4)记忆搜索和动态规划方式类似,是一种递归调用算法,将计算过的结果保存下来,避免重复计算,但是动态规划的计算是按照一定顺序的,比如子问题b的计算需要子问题a的结果,那么先计算a再算b,记忆搜索没管这些,哪个先来先计算哪个,将其保存。
2.应用场景:
(1)具有最优子结构:问题的最优策略的子策略总是最优的;(2)子问题的重叠性:
3.步骤:描述最优解的结构,递归定义最优解,自底向上计算,合并最优解
4.典型问题:全路径最短路径的Floyd算法,0-1背包问题,矩阵链乘法,求数组中连续子串的最大和问题,最长公共子序列问题,找零钱问题
5.动态规划算法的运行时间多数情况下是两个因素的乘积:子问题的个数*每个子问题有多少种选择。比如在矩阵链相乘问题中总共有O(n^2)个子问题,每个子问题至多有n-1个选择,所以时间复杂度为O(n^3)
6.0-1背包问题
问题:n件物品,第i件物品值vi元 重wi磅(vi和wi是整数),小偷的背包最多只能装W磅,请问他该带走那几样东西?
思想:物品 j 除外剩余 n-1件物品,能带走的物品最多中 W-wj。A(j,W)表示前 j 件物品中选择最佳组合放到重为W的包中,对于物体 j,一种可能是它加入前面的物品一起放进包里,那么就是 A(j-1,W-wi)+vj 即前 j-1件物品放在中 W-wj的包里的最好效果+放入j的价值;另一种可能就是 j不放进包里 包里仍旧放前j-1中的物品 那么价值为A(j-1,W)
而A(0,W )=0 即没有物品只有包, A(j,0)=0有物品没有包。可以能到 :当 wj <W时 A(j,W)=Max( A(j-1,W-wi)+vj , A(j-1,W)) , 当wj>W时 A(j,W)= A(j-1,W)
eg:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
class Knapsack{//物品 private String name; private int weight; private int value; public Knapsack(String name,int weight,int value){ this.name=name; this.weight=weight; this.value=value; } public String getName() { return name; } public int getWeight() { return weight; } public int getValue() { return value; } } public class Package { private int weightThr;//背包称重阈值 public Package(int weightThr){ this.weightThr=weightThr; } public int computeItem(Knapsack[] pack){ //System.out.print("packlen="+pack.length ); if(pack.length==0) return 0; //bestVal[i][j]表示前i件物品中放到承重为j的背包里 最大的价值 //重量+1是考虑到承重为0时防止数组越界 int[][] bestVal=new int[pack.length+1][weightThr+1]; //遍历包的称重j for(int j=0;j<=weightThr;j++){ //遍历物品i for(int i=0;i<=pack.length;i++){ if(i==0||j==0){ bestVal[i][j]=0; } else{ if(j<pack[i-1].getWeight()){//如果第i件物品重量大于总承重 则最优价值在前i-1种 bestVal[i][j]=bestVal[i-1][j]; System.out.println("物品过重"+pack[i].getWeight()+"\t此时i="+i+"\tj="+j); }else{ int w=pack[i-1].getWeight();//物品i的重量和价格,i是从0到length的,所以第i件对应的数组下标是i-1 int v=pack[i-1].getValue();//**************此处没搞懂为啥是i-1 //动态规划得出的最有解的递归公式 bestVal[i][j]=Math.max(bestVal[i-1][j], bestVal[i-1][j-w]+v); System.out.println("价格"+bestVal[i][j]+"\t此时i="+i+"\tj="+j); } } } } int bestValue=bestVal[pack.length][weightThr]; System.out.println("bestValue="+bestVal[pack.length][weightThr]); return bestValue; } public static void main(String[] args){ Knapsack[] pack=new Knapsack[]{ new Knapsack("a",2, 13), new Knapsack("b",1, 10), new Knapsack("c",3, 24), new Knapsack("d",2, 15), new Knapsack("e",4, 28), new Knapsack("f",5, 33), new Knapsack("g",3, 20), new Knapsack("h",1, 8) }; Package p=new Package(12); p.computeItem(pack); } }
一个背包有一定的承重cap,有N件物品,每件都有自己的价值,记录在数组v中,也都有自己的重量,记录在数组w中,每件物品只能选择要装入背包还是不装入背包,要求在不超过背包承重的前提下,选出物品的总价值最大。
给定物品的重量w价值v及物品数n和承重cap。请返回最大总价值。
public class Backpack {
public int maxValue(int[] w, int[] v, int n, int cap) {
// write code here
int[] dp=new int[cap+1];//承重
for(int i=0;i<n;i++){
for(int j=cap;j>=w[i];j--){
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
return dp[cap];
}
}
相关文章推荐
- 动态规划求解01背包相关的基本问题
- 算法导论学习笔记(十三):动态规划(三):01背包问题
- 动态规划之01背包
- 01背包问题之动态规划
- 动态规划实例(七):01背包问题最大价值
- HDU-CRB and His Birthday(动态规划本质未认清)---01背包与完全背包的结合!
- 动态规划之01 背包---Hd2602 Bone Collector
- 动态规划分析—以01背包为例
- 01背包问题动态规划详解(转载)
- 01背包问题动态规划详解(转载)
- 动态规划之01背包、完全背包问题
- 动态规划之背包01
- HDU 2546:饭卡(动态规划:01背包)
- 动态规划01背包问题
- 最大报销额(动态规划:01背包问题变形)
- 动态规划之01背包
- 01背包问题 -- 经典动态规划题
- 动态规划01背包
- 动态规划之背包问题01--java实现
- 动态规划之01背包—小P寻宝记——粗心的基友