/**
* Created by itworker365 on 5/10/2017.
*/
public class DynamicPlan {
public static void main (String[] args) {
int[] data = {1,-1,3,-5,2,1,9,-1};
// System.out.println(calcMaxSum(data));
int[] a = {1,-1,3,-5,2,1,9,-1};
int[] b = {1,-1,3,-5,2};
Lcs(a, b);
// packLoad();
}
//最大子段和,如果加上比最大的大,那么就加上,如果加起来是负数,那么就舍弃重置为0
private static int calcMaxSum (int[] data) {
int max = data[0];
for (int i = 1; i < data.length ; i++) {
int sum = max + data[i];
if (sum > max) {
max = sum;
} else if (sum < 0){
max = 0;
}
}
return max;
}
/**0-1(只只能选择放入或者不放入,没有其他可能),指定容量的背包,一堆一定数量和价值的物品,如何能在背包可容纳的情况下找到价值最高的负载方式
* V[i][j]表示前i个物品可以装入容量为j的背包的最大价值
* 可出现以下三种可能:
* 1. v[i][0]=v[0][j]=0; 初始状态,背包容量为0或者不装任何物品的时候价值为0
* 2. v[i][j]=v[i-1][j] 当w[i]>j 当放入物品i后背包超重,则无法放入
* 3. v[i][j]=max{v[i-1][j],v[i-1][j-w[i]]+v[i]} 当j>=w[i] 当第i个物品可以放入时,比较不放入 和 放入(减少容量,增加价值) 的价值,选择大的。
* */
private static void packLoad() {
int[] weight = {9, 3, 6};
int[] val = {4, 2, 3};
int packMax = 10;
int goodsCnt = val.length;
Method1(weight, val, packMax, goodsCnt);
Method2(weight, val, packMax, goodsCnt);
}
private static void Method2(int[] weight, int[] val, int packMax, int goodsCnt) {
int[] f = new int[packMax + 1];
for(int i = 1; i < f.length; i++){
//初始化为Integer.MIN_VALUE表示必须装满,初始化为0可以不满
f[i] = 0;
}
for(int i = 0; i < goodsCnt; i++){
for(int j = f.length - 1; j >= weight[i]; j--){
f[j] = Math.max(f[j], f[j - weight[i]] + val[i]);
}
}
for(int i = 0; i < f.length; i++){
System.out.print(f[i] + " ");
}
System.out.println("Max value: "+f[f.length - 1]);
}
private static void Method1(int[] weight, int[] val, int packMax, int goodsCnt) {
int[][] v = new int[goodsCnt + 1][packMax + 1];
//没带包,装不了
for(int i = 0; i < v.length; i++){
v[i][0] = 0;
}
//没物品,没得装
for(int i = 0; i < v[0].length; i++){
v[0][i] = 0;
}
//遍历所有物品
for(int i = 1; i < v.length; i++){
//遍历每个容量单元
for(int j = 1; j < v[0].length; j++){
//当前物品的重量大于背包容量,不放入
if(weight[i - 1] > j)
v[i][j] = v[i - 1][j];
else{
//如果放入价值更高,则放入,较少容积增加对应的价值,否则不放入
if(v[i - 1][j] < v[i - 1][j - weight[i - 1]] + val[i - 1]){
v[i][j] = v[i - 1][j - weight[i - 1]] + val[i - 1];
System.out.println("放入X:" + i + " " + j + " " + v[i][j]);
}else{
v[i][j] = v[i - 1][j];
}
}
}
}
PrintTwo(v);
}
private static void PrintTwo(int[][] v) {
for(int i = 0; i < v.length; i++){
for(int j = 0; j < v[0].length; j++){
System.out.print(v[i][j] + " ");
}
System.out.println();
}
}
/**
* 最长公共子序列
* c[i][j]表示两个长度分别为i,j的序列的最长公共子序列的长度
* c[0][j] 和 c[i][0]就是一个序列和一个空序列的公共子序列,所以就是空
* 寻找c[i][j]递推关系:
* 当序列1的第i个元素和第2个序列的第j个元素相同时,当前最大子序列增加一 c[i - 1][j - 1] + 1
* 当序列1的第i个元素和第2个序列的第j个元素不相同时,当前最大子序列为max(c[i - 1][j], c[i][j - 1])
* */
private static void Lcs(int[] a, int[] b) {
int alen = a.length;
int blen = b.length;
int[][] c = new int[alen][blen];
for (int i = 0; i < c.length; i++) {
c[i][0] = 0;
}
for (int i = 0; i < c[0].length; i++) {
c[0][i] = 0;
}
for (int i = 1; i < c.length; i++) {
for (int j = 1; j < c[0].length; j++) {
if (a[i - 1] != b[j - 1]) {
if (c[i - 1][j] > c[i][j - 1]) {
c[i][j] = c[i - 1][j];
} else {
c[i][j] = c[i][j - 1];
}
} else {
c[i][j] = c[i -1][j - 1] + 1;
}
}
}
PrintTwo(c);
}
}