HDOJ problem1003(DP)

<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;

}

点赞