Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (<= 10000). The second line contains K numbers, separated by a space.
For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.
10<br/>-10 1 2 3 4 -5 -23 3 7 -21
10 1 4
/*pat 牛客都AC了;牛客AC,但pat一个测试点无法通过,注意此case: 4 -2 0 0 -1 输出:0 0 0 */ #include <iostream> using namespace std; const int maxn=10001; int a[maxn],dp[maxn]; int main() { int n,flag=0,m,start,end,s,e; cin>>n; for(int i=0;i<n;i++) { cin>>a[i]; if(a[i]>=0) flag=1; } if(flag==0) { cout<<0<<" "<<a[0]<<" "<<a[n-1]<<endl; return 0; } m=dp[0]=a[0]; start=end=s=e=0; for(int i=1;i<n;i++) { if(a[i]>(dp[i-1]+a[i])) { dp[i]=a[i]; s=e=i; } else { dp[i]=dp[i-1]+a[i]; e=i; } if(m<dp[i]) { m=dp[i]; start=s; end=e; } } cout<<m<<" "<<a[start]<<" "<<a[end]<<endl; return 0; }
import java.util.Scanner;
/** * 1007. Maximum Subsequence Sum (25) * * @author Jacob * 注意:认真阅读题目,输出格式为:最大和序列 序列第一个数字(不是下标) 序列最后一个数字(不是下标) */ public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int[] arr = new int[N]; for (int i = 0; i < N; i++) arr[i] = sc.nextInt(); int max = Integer.MIN_VALUE, maxBegin = 0, maxEnd = 0; int sum = 0, tmpBegin = 0, tmpEnd = 0; for (int i = 0; i < N; i++) { if (sum < 0) { sum = 0; tmpBegin = arr[i]; } sum += arr[i]; tmpEnd = arr[i]; if (sum > max) { max = sum; maxBegin = tmpBegin; maxEnd = tmpEnd; } } if (max >= 0) System.out.println(max + " " + maxBegin + " " + maxEnd); else//结果小于0特殊处理 System.out.println(0 + " " + arr[0] + " " + arr[N - 1]); sc.close(); } }
#include <iostream> #include <vector> using namespace std; void MAXsum(vector<int> data, int length) { int Cursum = 0, Maxsum = 0; int start = 0, end = 0; for (int i = 0; i < length; i++) { Cursum += data[i]; if (Cursum < 0) Cursum = 0; if (Cursum > Maxsum) { Maxsum = Cursum; end = i; } } if (Maxsum == 0) cout << 0 << " " << data[0] << " " << data[length - 1] << endl; else { int sum = 0; int j = end; for (; j >= 0; j--) { sum += data[j]; if (sum == Maxsum) { start = j; // break; } } cout << Maxsum << " " << data[start] << " " << data[end] << endl; } } int main() { int length; while (cin >> length) { vector<int> data(length), res; for (int i = 0; i < length; i++) cin >> data[i]; MAXsum(data, length); } return 0; }
import java.util.Scanner; //乍看一下好像很难,暴力求解似乎要o(n^2),但是鉴于k的个数范围以及nowcoder对于时间的要求不用想也知道会超时。 //仔细分析一下,一次遍历的话其实只有2种情况: //①前面的和<0,那么当前数作为start重新开始一个序列吧! //②前面的和>=0(由于求最小ij所以要带着等于号), // 那么就判断:加上新数字的新总和newsum是否>存储着的之前的某次最大总和maxsum? // 大于的话就把数据存储下来作为新的总和maxsum=newsum! //用这种方法能确保maxsum是最大的! // public class Main { public static void main(String[] args) { Scanner in=new Scanner(System.in); int n=in.nextInt(); int a[]=new int[n]; for(int i=0;i<n;i++){ a[i]=in.nextInt(); } int oldsum=a[0]; //前面所有数字的总和 int start=0; //序列第一个数字 int maxstart=0; //记录最大总和时候的开始数字 int end=0; //序列最末数字(同时也是最大总和时候的最末数字) int newsum; //包含当前数字的新总和 int maxsum=Integer.MIN_VALUE; //用来记录最大总和 for(int i=1;i<n;i++){ if(oldsum<0){ start=a[i]; //当前数字作为序列第一个数啦 oldsum=0; //所以之前的总和清0咯 } newsum=oldsum+a[i]; oldsum=newsum; //下一次遍历时候的oldsum就是这次的newsum if(newsum>maxsum){ //更新并存储下最大和时候的数据 maxsum=newsum; end=a[i]; maxstart=start; } }if(maxsum<0){ System.out.println(0+ " "+a[0]+" "+a[n-1]); }else System.out.println(maxsum+" "+maxstart+" "+end); } }
#include<stdio.h> int main() { int a[10001],b[10001],minb[10001],i,N,h=1,t,sum=0; scanf("%d",&N); t=N; b[0]=minb[0]=0; for(i=1;i<=N;i++){ scanf("%d",a+i); b[i]=b[i-1]+a[i]; if(b[minb[i-1]]<=b[i]){ minb[i]=minb[i-1]; if(b[i]-b[minb[i]]>=sum){ h=minb[i]+1; t=i; sum=b[i]-b[minb[i]]; } } else minb[i]=i; } printf("%d %d %d",sum,a[h],a[t]); }
#include<iostream> #include<vector> #include<algorithm> using namespace std; int main(){ int n; cin>>n; vector<int> v(n); for(int i=0; i<n; ++i){ cin>>v[i]; } int beg, end; vector<int> dp(n); // dp[i] is max sum of subarray ending with v[i] dp[0]=v[0], end=0; for(int i=1; i<n; ++i){ dp[i] = max(dp[i-1]+v[i], v[i]); if(dp[i]>dp[end]){ end = i; } } int j, sum; for(j=end, sum=0; j>=0; --j){ sum += v[j]; if(sum==dp[end]){ beg = j; // get the smallest j if duplicated //break; } } if(dp[end]<0){ cout<<0<<" "<<v[0]<<" "<<v[n-1]<<endl; return 0; } cout<<dp[end]<<" "<<v[beg]<<" "<<v[end]<<endl; return 0; }
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
int main()
{
int sum,first,last;
int N = 0;
int input[10000];
scanf("%d",&N);
if(N==0)
{
cout<<"0 0 0"<<endl;
return 0;
}
for(int i=0;i<N;i++)
{
scanf("%d",&input[i]);
}
sum=input[0];
first = input[0];
last = input[0];
for(int i=0;i<N;i++)
{
int currentSum=0;
for(int j=i;j<N;j++)
{
//计算从input[i]计算到input[j]
currentSum+=input[j];
if(currentSum<0) break;
if(sum<currentSum)
{
sum = currentSum;
first = input[i];
last = input[j];
}
}
}
cout<<sum<<" "<<first<<" "<<last<<endl;
return 0;
}
核心是一道经典的DP题
import java.io.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int K = Integer.parseInt(br.readLine()); int[] nums = new int[K]; String[] input = br.readLine().split("\\s+"); int nonNegative = 0; for (int i = 0; i < K; ++i) { int tmp = Integer.parseInt(input[i]); nums[i] = tmp; if (tmp >= 0) { nonNegative++; } } input = null; if (nonNegative == 0) { System.out.format("%d %d %d\n", 0, nums[0], nums[K - 1]); return; } int maxSum = nums[0]; int maxSumIndex = 0; int maxSumLen = 1; int preMaxSum = nums[0]; int preMaxSumLen = 1; for (int i = 1; i < K; ++i) { if (preMaxSum >= 0) { preMaxSum += nums[i]; preMaxSumLen++; } else { preMaxSum = nums[i]; preMaxSumLen = 1; } if (nums[i] >= 0 && preMaxSum > maxSum) { maxSum = preMaxSum; maxSumIndex = i; maxSumLen = preMaxSumLen; } } System.out.format("%d %d %d\n", maxSum, nums[maxSumIndex - maxSumLen + 1], nums[maxSumIndex]); } }
// // Created by 硬汉J on 2021/2/25. // 全AC了,AC不了的,注意看题目,注意不要小于零 // #include <iostream> #include <vector> using namespace std; int main(){ int n; cin >> n; vector<int> initial(n); for (int i = 0; i < n; ++i) { cin >> initial[i]; } vector<int> dp(n); dp[0] = initial[0]; int end = 0; for (int i = 1; i < n; ++i) { dp[i] = max(dp[i - 1] + initial[i], initial[i]); if (dp[i] > dp[end]) { end = i; } } int j; int beg = 0; int sum; for (j = end, sum = 0; j >= 0; j--) { sum += initial[j]; if (sum == dp[end]) { beg = j; } } if (dp[end] < 0) { cout << 0 << " " << initial[beg] << " " << initial[n - 1] << endl; } else { cout << dp[end] << " " << initial[beg] << " " << initial[end] << endl; } return 0; }
#include<iostream> #include<vector> using namespace std; vector<int>myvect; vector<int>dp(10000); int main() { int n; bool flag = false; //判断是否有非负数 cin >> n; for (int i = 0; i < n; i++) { int a; cin >> a; if (a >= 0) flag = true; myvect.push_back(a); } if (flag == false) { cout << 0 << " " << myvect[0] << " " << myvect[n - 1] << endl; } else { //计算末端 dp[0] = myvect[0]; for (int i = 1; i < n; i++) { dp[i] = max(dp[i - 1] + myvect[i], myvect[i]); } int right = 0; for (int i = 1; i < n; i++) { if (dp[right] < dp[i]) right = i; } int res = dp[right]; //保存最大值 //计算始端 dp[n - 1] = myvect[n - 1]; for (int i = n - 2; i >= 0; i--) { dp[i] = max(dp[i + 1] + myvect[i], myvect[i]); } int left = 0; for (int i = 1; i < n; i++) { if (dp[left] < dp[i]) left = i; } cout << res << " " << myvect[left] << " " << myvect[right] << endl; } }
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 10001; int k, right, sum=-99999; int num[maxn]; int dp[maxn], left[maxn]={0}; bool flag = false; int main(void) { scanf("%d", &k); for(int i=0;i<k;++i){ scanf("%d", &num[i]); if(num[i]>=0) flag = true; } if(flag==false){ printf("%d %d %d\n", 0, num[0], num[k-1]); return 0; } right = k-1; dp[0] = num[0]; for(int i=1;i<k;++i){ dp[i] = max(num[i], dp[i-1]+num[i]); if(dp[i]>sum) { sum = dp[i]; right = i; } if(num[i]>(dp[i-1]+num[i])) left[i] = i; else left[i] = left[i-1]; } printf("%d %d %d\n", sum, num[left[right]], num[right]); return 0; }牛客AC,但是PAT3号测例过不去,郁闷....
//状态方程 dp[i]=max(dp[i-1]+A[i],A[i])// //###################################// #include<cstdio> const int maxn=10010; int dp[maxn][2]; //dp[i][0]记录最大连续子序列;dp[i][1]记录前端点; int A[maxn]; //数组 int main() { int k=0,num=0; //k数组个数,num负数个数 scanf("%d",&k); for(int i=0;i<k;i++) //输入 { scanf("%d",A+i); if(A[i]<0) num++; } if(num==k) { printf("%d %d %d\n",0,A[0],A[k-1]); return 0; } dp[0][0]=A[0]; //边界条件 dp[0][1]=0; int max=0; //记录最大子序列后端下标; for(int i=1;i<k;i++) { if(A[i]>dp[i-1][0]+A[i]) { dp[i][0]=A[i]; dp[i][1]=i; } else { dp[i][0]=A[i]+dp[i-1][0]; dp[i][1]=dp[i-1][1]; } if(dp[i][0]>dp[max][0]) //求最大子序列后端下标 max=i; } printf("%d %d %d\n",dp[max][0],A[dp[max][1]],A[max]); return 0; }
#include <iostream> using namespace std; int main(){ int K; //数组个数 cin >> K; int *a = new int [K]; //动态创建数组 int t=-1; for (int i=0; i<K; i++) { cin>>a[i]; //输入数组 if ((t==-1)&&(a[i]>=0)) { t=i; //记录第一次出现正数的下标 } } int sum=0, MaxSum=0, left=t, right=t, mayLeft=t; if (t==-1) { //如果都是负数,则直接默认最大和为0,输出首尾 left = 0; right = K-1; } else { for (int i=t; i<K; i++) { sum += a[i]; if (sum>MaxSum) { //更新最大子列 MaxSum = sum; left = mayLeft; right = i; } else if (sum<0) { //若和为负数,则将前面所有舍弃, 可能的最大子列左下标更新为i+1 mayLeft = i+1; sum = 0; } } } //输出 cout<<MaxSum<<' '<<a[left]<<' '<<a[right]; delete[] a; return 0; }PAT和牛客均通过了
为什么牛客有两个case没过,它也没给全我没过的case,不知道哪里出现问题,PAT都过了
思路:用两个结构体保存对比。 #include <iostream> #include <vector> #include <fstream> using namespace std; struct rlt { int sumMax; int startNum; int endNum; }; struct rlt FindMaxSubSquence(const vector<int> &v) { struct rlt temp; struct rlt max; temp.startNum = v[0]; temp.endNum = v[0]; temp.sumMax = v[0]; max = temp; for (int i = 1; i < v.size(); i++) { if (v[i] >= 0 && v[i - 1] > 0) { temp.endNum = v[i]; temp.sumMax += v[i]; if (temp.sumMax > max.sumMax) { max = temp; //cout << temp.startNum << " temp.startNum " << temp.endNum << " " << temp.sumMax << endl; } } else if (v[i] >= 0 && v[i - 1] <= 0) { if(temp.sumMax >= 0) { temp.endNum = v[i]; temp.sumMax += v[i]; if (temp.sumMax > max.sumMax) { max = temp; //cout << temp.startNum << " temp.startNum " << temp.endNum << " " << temp.sumMax << endl; } } else if(temp.sumMax < 0) { temp.sumMax = v[i]; temp.startNum = v[i]; temp.endNum = v[i]; if (temp.sumMax > max.sumMax) { max = temp; } } } else if (v[i] < 0) { temp.sumMax += v[i]; temp.endNum = v[i]; if (temp.sumMax > max.sumMax) { max = temp; } } } return max; } int main() { //ifstream cin("test.txt"); int n; while (cin >> n) { vector<int> v(n); bool negative = true; for (int i = 0; i < n; i++) { cin >> v[i]; if (v[i] >= 0) { negative = false; } } if (negative) { cout << 0 << " " << v[0] << " " << v[v.size() - 1] << endl; continue; } struct rlt max = FindMaxSubSquence(v); cout << max.sumMax << " " << max.startNum << " " << max.endNum << endl; } system("pause"); }
import java.util.Scanner;public class Main {