<span style="font-size:18px;"><span style="font-family: 'Microsoft YaHei'; background-color: rgb(255, 255, 255);">方法一:非动态规</span><span style="font-family: 'Microsoft YaHei'; background-color: rgb(255, 255, 255);">划</span></span>
<span style="font-family: 'Microsoft YaHei'; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java">package com.learn.bestcoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Problem1003 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int count = scan.nextInt();
int temp = count;
List<int[]> list = new ArrayList<>();
while(temp -- > 0){
int length = scan.nextInt();
int[] array = new int[length];
for(int i = 0; i < length; i ++)
array[i] = scan.nextInt();
list.add(array);
}
for(int i = 0; i < count; i ++){
maxSubSum(list.get(i), i );
if(i != count - 1)
System.out.println();
}
}
public static void maxSubSum(int[] array, int index){
int sum = 0;
int head = 0;
int temp = 0;
int tail = 0;
//int max = sum;
int max = array[0];
for(int i = 0; i < array.length; i ++){
sum += array[i];
if(sum > max){
max = sum;
tail = i;
head = temp;
}
if(sum < 0){
sum = 0;
temp = i + 1;
}
}
System.out.println("Case " + (++ index) + ":");
System.out.println(max + " " + (head + 1) + " " + (tail + 1));
}
}
<span style="font-family: 'Microsoft YaHei'; background-color: rgb(255, 255, 255);"><span style="font-size:18px;">方法二:动态规划</span></span>
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int count = scan.nextInt();
int temp = count;
List<int[]> list = new ArrayList<>();
while(temp -- > 0){
int length = scan.nextInt();
int[] array = new int[length];
for(int i = 0; i < length; i ++)
array[i] = scan.nextInt();
list.add(array);
}
for(int i = 0; i < count; i ++){
maxSubSum(list.get(i), i );
if(i != count - 1)
System.out.println();
}
}
public static void maxSubSum(int[] array, int index){
int[] dp = new int[array.length];
int head = 0;
int tail = 0;
int max = array[0];
dp[0] = array[0];
int temp = 0;
for(int i = 1; i < array.length; i ++){
if ( dp[ i - 1 ] >= 0 ) {
dp[ i ] = dp [ i - 1 ] + array [ i ];
}
else {
dp [ i ] = array [ i ];
temp = i;
}
if ( dp [ i ] > max ) {
max = dp [ i ];
tail = i;
head = temp;
}
}
System.out.println("Case " + (++ index) + ":");
System.out.println(max + " " + (head + 1) + " " + (tail + 1));
}
}
我一开始对动规方法理解错误的地方:
我搞错了父亲的结果和子序列结果的关系。我认为,可能存在一种情况,子序列0~8的最大子序列和为(2,5),这种情况下,父序列0~16的最大子序列肯定不能是包含(2,5)的,因为在(6,8)中间可能都是负数。但实际上,只要紧挨着(9,16)之前的序列的和大于0,就可以包含这个序列的。所以正确的父子关系是:
if ( dp[ i – 1 ] > 0 ) {
dp[ i ] = dp [ i – 1 ] + array [ i ];
}
else {
dp [ i ] = array [ i ];
temp = i;
}
if ( dp [ i ] > max ) {
max = dp [ i ];
tail = i;
head = temp;
}