看到动态规划的介绍,目前还是不能很透彻的理解状态转移的思想,看了一个动态规划的问题(即最大子路径和问题)的介绍之后还是动手写了一个程序,关于动态规划的思想,可能还需要再做更多的题目,慢慢的体会吧。
package com.wly.algorithmbase.dailyproblem;
import java.util.ArrayList;
/**
* 动态规划解最大子路径和问题
* @author wly
*
*/
public class MaxSubRouteSum {
public static void main(String[] args) {
//准备测试数据
ArrayList<Floor> list = new ArrayList<Floor>();
for(int i=0;i<4;i++) {
list.add(new Floor(i));
}
//打印测试数据
for(Floor f:list) {
f.print();
}
//输出运算结果
System.out.println("最大子路径和:" + getMaxSubRouteSum(list));
}
/**
* 自底向上求最大子路径和
* @param arrray
* @return
*/
public static int getMaxSubRouteSum(ArrayList<Floor> list) {
//以最后一层的元素的长度构造临时数组
int[] temp = null;
//得到"可以确定"的数据,这里指的是最后一层元素,可以这样理解:最大路径必定经过最后一层元素中的一个,实现的过程每次向上"合并"一层同时删除一半的"不可能"数据
for(int i=list.size()-1;i>=0;i--) {
Floor floor = list.get(i);
if(temp == null) { //最低一层
temp = new int[list.get(list.size()-1).getElems().length];
for(int j=0;j<floor.getElems().length;j++) {
temp[j] = floor.getElems()[j];
}
} else {
for(int j=0;j<=floor.getElems().length/2;j++) { //注意这里是<=,而不<。因为包含顶点
//---关键代码,舍弃"不可能是最优解"的数据信息,避免无用的计算步骤。同时保留当前"有潜力"的计算结果
temp[j] = Math.max(temp[2*j],temp[2*j + 1]) + floor.getElems()[j];
}
}
}
return temp[0];
}
}
/**
* 表示三角形树中的"层"
* @author wly
*
*/
class Floor {
int level; //当前层在三角新数中所在的层数,用来决定包含的elems的个数
int[] elems;
public Floor(int level) {
this.level = level;
elems = new int[(int)(Math.pow(2, level))];
for(int i=0;i<elems.length;i++) {
elems[i] = (int)(Math.random() * 10);
}
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int[] getElems() {
return elems;
}
public void setElems(int[] elems) {
this.elems = elems;
}
public void print() {
for(int i=0;i<elems.length;i++) {
System.out.print(elems[i] + " ");
}
System.out.println();
}
}
运行结果:
2
8 9
8 6 8 5
7 1 6 0 3 8 3 5
最大子路径和:27
这里的解题关键在于自低向上的迭代结果,不断的删除掉"不可能的数据"开介绍求解的计算量。
从动态规划的条件来论述:
1、最优子结构性质:一个最优化策略的子策略总是最优的。这句可以这么理解,我们知道最大路径必定是先经过顶点的,之后再经过顶点的左、右节点中的一个。因为顶点是固定的,相对于左右子节点来说是一样的,那么如果最大路劲经过的是左节点,那么左节点代表的最优解相对于右节点代表的最优解来说是一个更优解。因为左右子节点就包含了所有的解。所以左节点是最优解。
2、无后效性:每一个状态都代表了过去历史的一个完整总结。设共有n层,我们迭代到了第n - 10层,那么这第n-10层中的各一个元素,都代表了从n-11到n层的一个可能解,都一个一个n-11到n层的计算结果的总结。第n-11到n层的元素无法直接影响第n-9层的计算结果,只能通过第n-10层来影响。
3、子问题的重叠性:动态规划的关键在于解决冗余,本问题中表现出来的就是在向上迭代的过程中,删除了一些不可能成为最优解的数据,从而减少了求解的运算量,并复用了当前“尚且有希望"的解。
O啦~~~
转帖求保留出处:http://blog.youkuaiyun.com/u011638883/article/details/14243319
谢谢!!