您的位置:首页 > 编程语言 > Java开发

动态规划(java)

2016-04-24 16:06 531 查看
问题一:最大子组和问题

子组中的元素可能是正负或0,思路:

最大子组和就是所有可能的子组和中最大的,那么可能比较大的首先有一个初始值(0),然后如果有比初始值大的子组和,就用来替代当前的最大子组和,直到遍历结束再也没有比当前子组和更大的。

当子组和为负的时候,肯定不是我们期望的最大子组和的一部分,因为负的累积值和后续的子组元素的和,肯定小于后续子组元素的和。这时可以排除该子组和的元素,从使累计子组和为正的开始重新统计。

当遍历结束最大子组和等于初始值0时,说明数组元素都是非正的,那么遍历找出最大的负数。

/**
* @author Flying
*         题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
*         求所有子数组的和的最大值。要求时间复杂度为O(n)。 浙大数据结构课本上有 思路:
*         求连续数字之和,当和为负值,抛弃.当和为正值,比较其与最大值,如大于,则替换之
*         http://zhedahht.blog.163.com/blog/static/254111742007219147591/ *         http://blog.csdn.net/v_JULY_v/article/details/6444021 */
public class FindMaxSumOfSubArray {

/**
* @param args
*/
public static void main(String[] args) {
FindMaxSumOfSubArray f = new FindMaxSumOfSubArray();
int[] arr = { 1, -2, 3, 10, -4, 7, 2, -5 };
System.out.println("MaxSum:" + f.findMaxSum(arr));
}

public Integer findMaxSum(int[] arr) {
int curSum = 0;
int maxSum = 0;
int len = arr.length;

if (arr == null || len == 0) {
return null;
}

for (int i = 0; i < len; i++) {
curSum += arr[i];
if (curSum < 0) {
curSum = 0;
}
if (curSum > maxSum) {
maxSum = curSum;
}
}

// all data are negative
if (maxSum == 0) {
for (int i = 0; i < len; i++) {
if (i == 0) {
maxSum = arr[i];
}
if (arr[i] > maxSum) {
maxSum = arr[i];
}
}
}
return maxSum;
}
}


问题二:背包问题

这是我看过讲背包问题,最容易理解的帖子

http://m.blog.csdn.net/article/details?id=7722810

01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }

f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值。

Pi表示第i件物品的价值。

决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中吗 ?

题目描述:

有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?



只要你能通过找规律手工填写出上面这张表就算理解了01背包的动态规划算法。

首先要明确这张表是至底向上,从左到右生成的。

为了叙述方便,用e2单元格表示e行2列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为2的背包,那么这个背包的最大价值是0,因为e物品的重量是4,背包装不了。

对于d2单元格,表示只有物品e,d时,承重为2的背包,所能装入的最大价值,仍然是0,因为物品e,d都不是这个背包能装的。

同理,c2=0,b2=3,a2=6。

对于承重为8的背包,a8=15,是怎么得出的呢?

根据01背包的状态转换方程,需要考察两个值,

一个是f[i-1,j],对于这个例子来说就是b8的值9,另一个是f[i-1,j-Wi]+Pi;

在这里,

f[i-1,j]表示我有一个承重为8的背包,当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值

f[i-1,j-Wi]表示我有一个承重为6的背包(等于当前背包承重减去物品a的重量),当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值

f[i-1,j-Wi]就是指单元格b6,值为9,Pi指的是a物品的价值,即6

由于f[i-1,j-Wi]+Pi = 9 + 6 = 15 大于f[i-1,j] = 9,所以物品a应该放入承重为8的背包

下面是java实现:

/article/2488622.html

public class KnapsackProblem {
/** 指定背包 */
private Knapsack[] bags;

/** 总承重  */
private int totalWeight;

/** 给定背包数量  */
private int n;

/** 前 n 个背包,总承重为 totalWeight 的最优值矩阵  */
private int[][] bestValues;

/** 前 n 个背包,总承重为 totalWeight 的最优值 */
private int bestValue;

/** 前 n 个背包,总承重为 totalWeight 的最优解的物品组成 */
private ArrayList<Knapsack> bestSolution;

public KnapsackProblem(Knapsack[] bags, int totalWeight) {
this.bags = bags;
this.totalWeight = totalWeight;
this.n = bags.length;
if (bestValues == null) {
bestValues = new int[n+1][totalWeight+1];
}
}

/**
* 求解前 n 个背包、给定总承重为 totalWeight 下的背包问题
*
*/
public void solve() {

System.out.println("给定背包:");
for(Knapsack b: bags) {
System.out.println(b);
}
System.out.println("给定总承重: " + totalWeight);

// 求解最优值
for (int j = 0; j <= totalWeight; j++) {
for (int i = 0; i <= n; i++) {

if (i == 0 || j == 0) {
bestValues[i][j] = 0;
}
else
{
// 如果第 i 个背包重量大于总承重,则最优解存在于前 i-1 个背包中,
// 注意:第 i 个背包是 bags[i-1]
if (j < bags[i-1].getWeight()) {
bestValues[i][j] = bestValues[i-1][j];
}
else
{
// 如果第 i 个背包不大于总承重,则最优解要么是包含第 i 个背包的最优解,
// 要么是不包含第 i 个背包的最优解, 取两者最大值,这里采用了分类讨论法
// 第 i 个背包的重量 iweight 和价值 ivalue
int iweight = bags[i-1].getWeight();
int ivalue = bags[i-1].getValue();
bestValues[i][j] =
Math.max(bestValues[i-1][j], ivalue + bestValues[i-1][j-iweight]);
} // else
} //else
} //for
} //for

// 求解背包组成
if (bestSolution == null) {
bestSolution = new ArrayList<Knapsack>();
}
int tempWeight = totalWeight;
for (int i=n; i >= 1; i--) {
if (bestValues[i][tempWeight] > bestValues[i-1][tempWeight]) {
bestSolution.add(bags[i-1]);  // bags[i-1] 表示第 i 个背包
tempWeight -= bags[i-1].getWeight();
}
if (tempWeight == 0) { break; }
}
bestValue = bestValues
[totalWeight];
}

/**
* 获得前  n 个背包, 总承重为 totalWeight 的背包问题的最优解值
* 调用条件: 必须先调用 solve 方法
*
*/
public int getBestValue() {
return bestValue;
}

/**
* 获得前  n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵
* 调用条件: 必须先调用 solve 方法
*
*/
public int[][] getBestValues() {

return bestValues;
}

/**
* 获得前  n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵
* 调用条件: 必须先调用 solve 方法
*
*/
public ArrayList<Knapsack> getBestSolution() {
return bestSolution;
}
public static void main(String[] args) {

Knapsack[] bags = new Knapsack[] {
new Knapsack(2,13), new Knapsack(1,10),
new Knapsack(3,24), new Knapsack(2,15),
new Knapsack(4,28), new Knapsack(5,33),
new Knapsack(3,20), new Knapsack(1, 8)
};
int totalWeight = 12;
KnapsackProblem kp = new KnapsackProblem(bags, totalWeight);

kp.solve();
System.out.println(" -------- 该背包问题实例的解: --------- ");
System.out.println("最优值:" + kp.getBestValue());
System.out.println("最优解【选取的背包】: ");
System.out.println(kp.getBestSolution());
System.out.println("最优值矩阵:");
int[][] bestValues = kp.getBestValues();
for (int i=0; i < bestValues.length; i++) {
for (int j=0; j < bestValues[i].length; j++) {
System.out.printf("%-5d", bestValues[i][j]);
}
System.out.println();
}
}

}


public class Knapsack {
/** 背包重量  */
private int weight;

/** 背包物品价值  */
private int value;
/***
* 构造器
*/
public Knapsack(int weight, int value) {
this.value = value;
this.weight = weight;
}
public int getWeight() {
return weight;
}

public int getValue() {
return value;
}

public String toString() {
return "[weight: " + weight + " " + "value: " + value + "]";
}

}


最长公共子串

/article/9834847.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: