今天剖析最大化石头堆问题,采用O(n^3)编程,问题不难,但很典型,也有更好的接近O(N^2)的代码进行优化。
问题如下:
在一个圆形操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最大得分。
思路剖析:
石头堆围成一个圆形操场,每次合并只能合并相邻堆,马上想到典型的邻接问题和菲波纳契数列,属于从局部最优到全局最优,并不断更新最大得分,直到运算完成才出结果。显然,最后的最大得分,并没有将随机输入进行综合考察,进行分布式,而是每一次的最大得分更新,都非常紧凑的依赖于前一次的计算,那么这就是经典菲波纳契规划问题。
流程如下:
选取对角线数组作为初始值----设置间隔递增-----动态更新每个间隔的合并值,并保存于数组-----计算完成,得出最大得分,和计算出最大得分的整条路线。
以下是本人的代码,稍微对经典DP问题进行修改,可以放入IDE尝试运行下,应该不成问题。这个输入最后求得的解,是2596,你可以把这个输入换成其他随机输入,
但是记得,这个一维数组的最后一个值,必须等于第一个初始值,追加上去。

public class RoundedStoneMaxMinHeap {
public static RoundedStoneMaxMinHeap mMaxMin;
public void bestOutput(int[] group) {
int n = group.length;
if (n > 0) {
int[][] realTable = new int[n + 1][n + 1];
int[][] lastTable = new int[n + 1][n + 1];
for (int k = 1; k <= n; k++) {
for (int j = 1; j <= n; j++) {
if (j == k) {
realTable[j][k] = group[k-1];
} else {
realTable[j][k] = 0;
}
lastTable[j][k] = 0;
}
}
int total = 0;
int temp = 0;
for (int k = 1; k <= n; k++) {
for (int left = 1; left <= n - k; left++) {
int right = left + k;
for (int i = left; i < right; i++) {
temp = realTable[left][i] + realTable[i + 1][right];
if (temp > realTable[left][right]) {
realTable[left][right] = temp;
lastTable[left][right] = i;
if(temp > total)
total = temp;
}
}
System.out.print(realTable[left][right] + ",");
}
System.out.println("");
}
System.out.print(total + " = max num");
}
}
public static void main(String[] args) {
int[] input = new int[] { 100, 80, 175, 220, 15, 3, 400, 872, 354, 57,
86, 24, 110, 100 };
mMaxMin = new RoundedStoneMaxMinHeap();
mMaxMin.bestOutput(input);
}
}

浙公网安备 33010602011771号