动态规划-钢条切割--DP_1
2016-08-31 23:01
246 查看
扯犊子:急了我,我发现网上的笔试中经常会出现动态规划的题目,所以我建议各位IT程序猿,如果想去好一点的公司,这个是必须要会的。
DP:动态规划通常是用来解决最优化的问题的,在这类问题中我们通过做出一组选择来达到最优解,在做出选择的同时,通常会生成和原问题相同的子问题。当多于一个选择子集都生成相同的子问题时,DP会很有效,其关键技术就是对每个这样的子问题都保存其解,当重复出现时可以避免重复求解。递归解决f(n)= f(n-1)+f(n-2)这个问题时,用DP解决会避免很多问题的重复求解。
分治法:分治法是将原问题划分为互不相交的子问题,递归的求出他们的解,然后组合起来就是原问题的解。DP也是将原问题划分为很多子问题,但是这些子问题有重复的,DP求解问题,将子问题的解保存下来,遇到相同的子问题不必重复求解。
问题:
钢条切割
DP解决钢条切割的方案半伪代码
具体的想知道跟我讨论吧
DP:动态规划通常是用来解决最优化的问题的,在这类问题中我们通过做出一组选择来达到最优解,在做出选择的同时,通常会生成和原问题相同的子问题。当多于一个选择子集都生成相同的子问题时,DP会很有效,其关键技术就是对每个这样的子问题都保存其解,当重复出现时可以避免重复求解。递归解决f(n)= f(n-1)+f(n-2)这个问题时,用DP解决会避免很多问题的重复求解。
分治法:分治法是将原问题划分为互不相交的子问题,递归的求出他们的解,然后组合起来就是原问题的解。DP也是将原问题划分为很多子问题,但是这些子问题有重复的,DP求解问题,将子问题的解保存下来,遇到相同的子问题不必重复求解。
问题:
钢条切割
DP解决钢条切割的方案半伪代码
@自顶向下: @定义数组 price[];价格数组 length 钢条的长度 res[length+1]存放结果数组,0-0,1-1 solu[length] 切割方案的组成 @初始化数组 //此方法:前三个参数为数组,后一个参数为长度 intial(res,solu,price,length){ //定义为负无穷的目的就是说明次结果并未求出,例如res[1]=负无穷,说明长度为1的价值并未求出 res[0]=0,res[1~length+1]=负无穷 execute(res,solu,price,length) } @ 执行方法 execute(res,solu,price,length){ //条件1,说明此数组已经求出结果,不必重复求 if(res[length] > 0) return res[length]; //条件2,如果长度为0,直接返回结果 int q = res[length]; if(length == 0) return q; //长度为 1~length else{ for(i = 1~length){ q = max(q,price[i-1]+execute(res,solu,price,length-i)) if(res[length] < q){ res[length] = q; solu[length-1] = i; } } } } @自低向上 @定义数组 price[];价格数组 length 钢条的长度 res[length+1]存放结果数组,0-0,1-1 solu[length] 切割方案的组成 @ 执行方法 execute(res,solu,price,length){ for(i = 1~length){ q = -1; for(j=1~i){ q = Max(q,price[j]+res[i-j]); if(res[i] <q){ res[i] = q; solu[i-1]=i; } } } }
package dynamic.planning; /* * 钢条切割:保存每种的切割方案 */ public class CuttingBars 4000 All { public static void main(String[] args) { int price[] = { 1, 5, 8, 9, 10 }; int length = 5; // 结果 int res[] = new int[length + 1]; // 切割方案 int solu[] = new int[length]; executeDownToTop(res, price, solu, length); for (int i = 0; i < res.length; i++) { System.out.print(res[i] + " "); } System.out.println(); for (int i = length - 1; i >= 0;) { System.out.print(solu[i] + " "); i = i - solu[i]; } } public static void inital(int res[], int[] price, int solu[], int length) { for (int i = 1; i < res.length; i++) { res[i] = Integer.MIN_VALUE; } System.out.println(executeTopToDown(res, price, solu, length)); for (int i = 0; i < res.length; i++) { System.out.print(res[i] + " "); } System.out.println(); for (int i = length - 1; i >= 0;) { System.out.print(solu[i] + " "); i = i - solu[i]; } } // 自顶向下 public static int executeTopToDown(int res[], int[] price, int solu[], int length) { if (res[length] > 0) { return res[length]; } int q = res[length]; if (length == 0) return q; else { /* * 自顶向下5->4->3->2->1->0 要求5就要求4、3、2、1 * * 当长度为5时求最大的价值:切割方案1+4、2+3、3+2、4+1、5+0。 */ for (int i = 1; i <= length; i++) { // 给定i长度的价值 int inter1 = price[i - 1]; int inter2 = executeTopToDown(res, price, solu, length - i); q = inter1 + inter2; if (res[length] < q) { res[length] = q; solu[length - 1] = i; } } } return q; } // 自低向上 --这个简单一点 从1开始求解,2,3,... public static int executeDownToTop(int res[], int[] price, int solu[], int length) { int q = 0; for (int i = 1; i <= length; i++) { q = -1; for (int j = 1; j <= i; j++) { q = price[j - 1] + res[i - j]; if (q > res[i]) { res[i] = q; solu[i - 1] = j; } } } return q; } }
具体的想知道跟我讨论吧