hdu - 1003 - Max Sum
来源:互联网 发布:美英特殊关系知乎 编辑:程序博客网 时间:2024/05/06 02:19
题意:求一个数列的最大连续和,并输出起止端。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
——>>做这题三次了,似乎每次的写法都不一样,现在觉得,至少有两种想法可解决此题:
一、以数列的每个数为末端的最大连续和从左到右遍历一次。
二、分治与递归,[L, R)的最大连续和,取其中点M = L + (R-L) / 2,最大连续和要么在[L, M),要么在[M, R),要么横穿M。
两种想法都是dp……
直接dp:
#include <cstdio>using namespace std;const int maxn = 100000 + 10;int a[maxn];int main(){ int T, N, i, cnt = 1; scanf("%d", &T); while(T--) { scanf("%d", &N); for(i = 0; i < N; i++) scanf("%d", &a[i]); int max_sum = a[0], max_L = 0, max_R = 0, cur_sum = a[0], L = 0, R = 0; for(i = 1; i < N; i++) { if(cur_sum < 0) { cur_sum = a[i]; L = R = i; } else { cur_sum += a[i]; R = i; } if(cur_sum > max_sum) { max_sum = cur_sum; max_L = L; max_R = R; } } printf("Case %d:\n", cnt++); printf("%d %d %d\n", max_sum, max_L+1, max_R+1); if(T) printf("\n"); } return 0;}
分治与递归dp:
#include <iostream>using namespace std;const int maxn = 100000 + 10; //1<=N<=100000int A[maxn]; //A为输入数组int dp(int L, int R, int &pre, int &suf) //找数组A中[L, R)上的最大连续和,其中最大连续和的左边界放入pre中,右边界放入suf中{ if(R - L == 1) //如果只有一个元素,直接返回 { pre = L; suf = L; return A[L]; } int M = L + (R - L)/2, i, l_pre, l_suf, r_pre, r_suf; //取中值M进行分治 int max_left = dp(L, M, l_pre, l_suf); //求左串的最大连续和 int max_right = dp(M, R, r_pre, r_suf); //示右串的最大连续和 int max_pre = -214748364, max_suf = -214748364, sum = 0; //max_suf为左串的最大后缀和,max_pre为右串的最大前缀和 for(i = M-1; i >= L; i--) //求max_suf { sum += A[i]; if(sum >= max_suf) //更新 { pre = i; //预先设[L, R)上的最大连续和横穿M,将其最大连续和的左边界更新 max_suf = sum; } } sum = 0; for(i = M; i < R; i++) //求max_pre { sum += A[i]; if(sum > max_pre) //更新 { suf = i; //预先设[L, R)上的最大连续和横穿M,将其最大连续和的右边界更新 max_pre = sum; } } sum = max_suf + max_pre; //横穿M的最大连续和 int MAX; //要返回的最大连续和 if(max_left >= sum) //当左子串的最大连续和大于等于横穿M的最大连续和时(注意不用>,因为相等的时候取先出现的) { pre = l_pre; //更新最大连续和的左边界 suf = l_suf; //更新最大连续和的右边界 MAX = max_left; //更新最大连续和 } else { MAX = sum; //更新最大连续和 } if(max_right > MAX) //当右子串的最大连续和大于横穿M的最大连续和时(注意不用>=,因为相等的时候取先出现的) { pre = r_pre; //更新最大连续和的左边界 suf = r_suf; //更新最大连续和的右边界 MAX = max_right; //更新最大连续和 } return MAX; //返回最大连续和}int main(){ int T, N, i, cnt = 1, l, r; cin>>T; while(T--) { cin>>N; for(i = 1; i <= N; i++) cin>>A[i]; cout<<"Case "<<cnt++<<":"<<endl; int max_sum = dp(1, N+1, l, r); cout<<max_sum<<" "<<l<<" "<<r<<endl; if(T) cout<<endl; } return 0;}
直接dp的Java版:
import java.util.Scanner;public class Main {final static int maxn = 100000 + 10;static int a[] = new int[maxn];public static void main(String[] args) {int T, N, i, cnt = 1;Scanner cin = new Scanner(System.in);T = cin.nextInt();while(T-->0){N = cin.nextInt();for(i = 0; i < N; i++) a[i] = cin.nextInt();int max_sum = a[0], max_L = 0, max_R = 0;int cur_sum = a[0], L = 0, R = 0;for(i = 1; i < N; i++){if(cur_sum < 0){cur_sum = a[i];L = R = i;}else{cur_sum += a[i];R = i;}if(cur_sum > max_sum){max_sum = cur_sum;max_L = L;max_R = R;}}System.out.println("Case "+(cnt++)+":");System.out.println(max_sum+" "+(max_L+1)+" "+(max_R+1));if(T>0) System.out.println();}cin.close();}}
- HDU 1003 Max Sum
- hdu 1003 Max Sum
- hdu 1003 Max Sum
- HDU-1003 max sum
- HDU 1003 - Max Sum
- HDU 1003 Max Sum
- hdu 1003 Max Sum
- HDU 1003 Max Sum
- HDU 1003 Max Sum
- hdu 1003 max sum
- HDU 1003 Max Sum
- hdu 1003 Max Sum
- HDU 1003 Max Sum
- hdu 1003 Max Sum
- HDU 1003 Max Sum
- Hdu 1003 - Max Sum
- HDU-1003-Max Sum
- hdu - 1003 - Max Sum
- spring_mvc注解例子
- Android UI主线程和子线程
- Oracle忘记用户名密码怎样办?
- Spring的自动扫描注入
- 关于UIMA的个人理解
- hdu - 1003 - Max Sum
- JAVA操作properties文件
- 替换properties文件 占位符
- 括号匹配问题
- log4全面配置
- WPF获取控件位置的方法
- 大二下学期第二周项目1————有序的结构体数组
- 国际化
- java中的properties