codeforces B.Maximum Absurdity 解题报告

题目链接:http://codeforces.com/contest/332/problem/B

题意:在一个序列中,在所有长度为k的区间里找出两个不重叠的最大和,输出这两个最大和所对应的开头的位置a和b。

     一开始没有想到用dp来做,于是有了以下的错误思路(读者可以忽略):声明一个结构体,包括head(保存起始点)、tail(保存结束点)还有sum(保存长度为k的区间的和)。计算出整个序列所有k个小区间的和sum,按sum从大到小排序(隐含的弊端:排序会导致区间与区间之间起始点和结束点的位置很不确定)由于a、b不能相交,所以当找到没有重叠的部分,就找到当前最优解,但不一定是整个题目的最优解。还要比较各个序列的最优解,以便找到整个题目的最优解,但是重叠的判断会有很多种情况(sum的排序导致的),于是参考了别人的代码......

     正确的思路:当然就是用dp做啦。而且,也是需要计算出所有长度为k的区间的和,按顺序保存在数组b[]中(比我的方法好多啦)。接下来是找出状态转移方程:  max{b[i]} + b[i+k]。另外,考虑到数据比较大,所以用长整型(_int 64)来保存数据。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 using namespace std;
 5 
 6 #define LL __int64
 7 const int maxn = 200000 + 10;
 8 LL a[maxn], b[maxn];
 9 
10 int main()
11 {
12     int i, j, n, k;
13     LL tl, maxt, maxl, maxr, ans;
14     while (scanf("%d%d", &n, &k) != EOF)
15     {
16         LL temp = 0;
17         for (i = 1; i <= n; i++)
18         {
19             scanf("%I64d", &temp);
20             a[i] = a[i-1] + temp;       // a[i]保存的是从第1至第i个元素的总和 
21         //  printf("a[%d] = %I64d\t", i, a[i]);
22         }
23         for (i = 0, j = 1; i <= n-k; i++, j++)
24         {
25             b[j] = a[i+k] - a[i];    // b[j]保存的是所有长度为k的区间的总和
26 // printf("b[%d] = %I64d\t", j, b[j]); 27 } 28 maxt = ans = b[1]; 29 tl = maxl = maxr = 1; // maxl: a maxr:b
30 for (i = 1; i+k <= n-k+1; i++) // 循环的判别要注意,要保证取值不能越界
31 { 32 if (b[i] > ans) // 状态转移方程中的max{b[i]},用ans保存
33 { 34 ans = b[i]; 35 tl = i; 36 // printf("ans = %I64d\n", ans); 37 } 38 if (b[i+k] + ans > maxt) 39 { 40 maxt= b[i+k] + ans; 41 maxl = tl; 42 maxr = i+k; 43 // printf("maxt = %I64d\n", maxt); 44 // printf("maxl = %I64d\tmaxr = %I64d\n", maxl, maxr); 45 } 46 } 47 printf("%I64d %I64d\n", maxl, maxr); 48 } 49 return 0; 50 }

  

原文地址:https://www.cnblogs.com/windysai/p/3220305.html