これは興味深い問題です。パーティションの合計が単調に増加する順序である必要があることを除いて、元のパーティションの問題に似ています。動的計画法の再帰関係は次のように与えられます。
numP[i] = max {numP[i-j] + 1} for those values of j (1<=j<=i) such that sum(A[i-j,i-j+1,...,i] >= lastSum[i-j])
= 1 for i = 1
lastSum[i] = the sum of the last partition in numP[i] solution.
= A[0] for i = 1;
lastI[i] = starting index of the last partition in numP[i] solution; // this is needed to obtain the partitions in the solution
ここでは、配列のnumP[i]
最初の要素を使用して取得できるパーティションの最大数を表しますi
(配列はゼロ インデックスではありません)。配列の要素を考慮してすべての可能な解を再帰的に見つけようとし、ith
得られたパーティションの最大数を出力します。j
最後のパーティションが開始するインデックスを表します。lastSum[i]
でありlastI[i]
、既に上で定義されています。
動的プログラミング ソリューションの Java 実装を次に示します。
void getMaxPartitions (int[] A) {
int len = A.length;
int[] numP = new int[len+1];
int[] lastSum = new int[len+1];
int[] lastI = new int[len+1];
numP[1] = 1;
lastSum[1] = A[0];
lastI[1] = 0;
for (int i = 2; i <= len; i++) {
int maxIndex = 0;
int maxPs = 0;
int maxSum = 0;
for(int j = 1; j <= i; j++) {
int sum = 0;
for(int k = i-j; k < i; k++) {
sum += A[k];
}
if(sum >= lastSum[i-j]) {
if(maxPs < numP[i-j] + 1) {
maxPs = numP[i-j]+1;
maxSum = sum;
maxIndex = i-j;
}
}
}
numP[i] = maxPs;
lastSum[i] = maxSum;
lastI[i] = maxIndex;
}
System.out.println("max partitions = " + numP[len]);
int i = len;
while (i > 0) {
System.out.println(lastSum[i]);
i = lastI[i];
}
}
プログラムは、次の入力についてテストされ、結果は以下のとおりです。
(1) {3,4,7,1,5,4,11} max partitions = 5 {3,4,8,9,11}
(2) {1,2,3,4,5,6,7,11} max partitions = 8 {1,2,3,4,5,6,7,11}
(3) {1,1,1,1,1,1,1,1,1} max partitions = 9 {1,1,1,1,1,1,1,1,1}
(4) {9,8,7,6,5,4,3,2,1} max partitions = 3 {9,15,21}
(5) {40,8,7,6,5,4,3,2,1} max partitions = 1 {76}