HOJ 1003题 题解

     杭电OJ 1003题题目链接:点击打开链接

     本题思路: 为了避免复杂的判断,将测试用例全部为负数的情况单独处理。

  (1)如果某个测试用例全部为负数,则遍历数据,找到最大的数,记录下标,该下标既是子序列的开始下标,也是结束下标。

  (2)如果某个测试用例不全为负,则采用动态规划的方法,计算一系列的子序列和。具体方法如下:假如测试用例(用nums[5]数组保存)为5 6 -1 5 4 -7,使用长度为5的数组sums保存“和”的中间结果,设置sums[0]=6,sums[1]~sum[4]的值使用循环,通过动态计算然后赋值。例如,设置i为循环变量,如果sums[i-1] 为负,则sums[i]赋值为nums[i],也就是说不加上前面的“中间和”(因为前面的中间和为负嘛,所以加上这个负的中间和就找不到最大值了);如果sums[i-1]>=0,则sums[i]在此基础上加上nums[i](如此非负数的累加才能找到最大值嘛,此时nums[i]其实就是某一个子序列的和,比如可能是子序列5+6+(-1)+5的和)。按照这种方法将sums[0]---sums[4]全部赋值完毕后,遍历,最大的数即为要找的最大值。最大值的下标即为子序列的结束下标,从最大值的下标(结束值下标)向前找到第一个负数,也就找到了子序列的开始下标(因为如果nums[k]为负,则在nums[k+1]赋值的时候,就会放弃k之前的“中间和”,重新开始找最大值,所以该位置为子序列的分界点)。


    本题AC示例代码如下:

import java.io.BufferedInputStream;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		int count = cin.nextInt();
		//测试用例是否全部为负数
		boolean isNegative = true;
		for (int i = 0; i 0){
					isNegative = false;
				}
				nums[j] = num;
			}
			
			//重复使用nums数组保存相加的中间结果
			for (int j = 1; j < rowCount; j++) {
				if (nums[j - 1] >= 0) {
					nums[j] += nums[j - 1];
				}
				//其他情况,nums[j]的值不变
			}

			// 遍历中间结果数组nums,找到最大的数max即为子序列最大和;
			//(注意:找第一个最大的数,nums数组可能有多个数max)
			// 该子序列起始位置为:数max向前找到第一个负数,然后加1;
			// 该子序列的结束位置为:数max所在的位置。
			int max = nums[0];
			// 使用beginFlag、endFlag记录开始和结束下标
			int beginFlag = 0;
			int endFlag = 0;
			for (int k = 0; k < rowCount; k++) {
				if (nums[k] > max) {
					max = nums[k];
					// 随着最大值更新的 “结束下标值”,循环结束后,endFlag即为正确的结束下标
					endFlag = k;
				}
			}
			// 寻找开始下标:从最终结束下标向前遍历nums数组,向前找到第一个负数,注意找到后需要加1才是正确的开始下标
			// 特殊情况考虑:全为负数;
			if(isNegative){
				beginFlag = endFlag;
			} else {
				for (int k = endFlag-1; k >= 0; k--) {
					if (nums[k] < 0) {
						beginFlag = k + 1;
						break;
					}
				}
			}
			// 按照要求的格式进行输出
			// 第一行
			if (i == 0) {
				System.out.println("Case " + (i + 1) + ":");
				System.out.print(max + " ");
				System.out.print(beginFlag + 1 + " ");
				System.out.println(endFlag + 1);
			}
			// 第二行即之后
			else {
				System.out.println();
				System.out.println("Case " + (i + 1) + ":");
				System.out.print(max + " ");
				System.out.print(beginFlag + 1 + " ");
				System.out.println(endFlag + 1);
			}
		}
		
		cin.close();
	}
}



  顺便给出一些测试用例和正确的答案吼:

8
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
3 -2 1 -2
3 -2 -2 -2
7 -3 5 -7 3 4 -1 5
4 -3 -5 -2 -1
3 -3 -2 -7
4 0 0 0 0

Case 1:
14 1 4

Case 2:
7 1 6

Case 3:
1 2 2

Case 4:
-2 1 1

Case 5:
11 4 7

Case 6:
-1 4 4

Case 7:
-2 2 2

Case 8:
0 1 1


      欢迎大家评论指正讨论,不喜勿喷。

你可能感兴趣的:(HOJ题解)