您的位置:首页 > 其它

动态规划-钢条切割--DP_1

2016-08-31 23:01 246 查看
扯犊子:急了我,我发现网上的笔试中经常会出现动态规划的题目,所以我建议各位IT程序猿,如果想去好一点的公司,这个是必须要会的。

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;
}
}


具体的想知道跟我讨论吧 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: