zoukankan      html  css  js  c++  java
  • 51nod1254 最大子段和 V2 DP

    ~~~题面~~~

    题解:

      表示今天做题一点都不顺。。。。

      这题也是看了题解思路然后自己想转移的。

      看的题解其实不是这道题,但是是这道题的加强版,因为那道题允许交换k对数。

      因为我们选出的是连续的一段,所以假设我们选了某一段,那么原序列将会被分为3段,我们设这3段分别是第0段,第1段和第2段,我们假设我们选出的区间是第1段。

      那么我们的目的就是要从第0段或第2段中选出一个数,从第1段中剔除一个数,使得1段中剩余数+选出数之和最大。  

      所以我们设f[i][j][k][l]表示DP到i位,已经选出了j个数,剔除了k个数, 当前在第l段的最大值。

      那么每次转移的时候就枚举一下当前的状态,如果当前在第0段or第2段,那么就考虑选出一个数or不选一个数。

      如果当前在第1段,那么就考虑剔除这个数or保留这个数。

      最后的答案就枚举一下最后一个数是属于哪一段,是否有交换(如果交换就是选出1个数,剔除1个数)。

      这里虽然强制交换,但和可以选择交换不交换是等效的。

      因为当n <= 2的时候,交换显然无意义。当n > 2的时候,属于1段的数的个数和不属于1段的数的个数中肯定有一个>= 2,那么交换一个段内部的数肯定是不会产生影响的,所以和不交换一样。

      因此选择不交换一定是合法的。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 50100
     5 #define LL long long
     6 
     7 int n;
     8 int s[AC];
     9 LL f[AC][2][2][3];//DP到i位, 选出j个,剔除k个,当前在第l段的最大值。
    10 
    11 inline int read()
    12 {
    13     int x = 0;char c = getchar();bool z = false;
    14     while(c > '9' || c < '0') 
    15     {
    16         if(c == '-') z = true;
    17         c = getchar();
    18     }
    19     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    20     if(!z) return x; 
    21     else return -x;
    22 }
    23 
    24 void pre()
    25 {
    26     n = read();
    27     for(R i = 1; i <= n; i ++) s[i] = read();
    28 }
    29 
    30 LL Max(LL a, LL b, LL c)
    31 {
    32     if(a > b && a > c) return a;
    33     else if(b > c) return b;
    34     else return c;
    35 }
    36 
    37 LL Max_(LL a, LL b, LL c, LL d)
    38 {
    39     if(a > b && a > c && a > d) return a;
    40     else if(b > c && b > d) return b;
    41     else if(c > d) return c;
    42     else return d;
    43 }
    44 
    45 void work()
    46 {
    47     for(R i = 1; i <= n; i ++)
    48     {
    49          f[i][1][0][0] = max(f[i - 1][1][0][0], f[i - 1][0][0][0] + s[i]);
    50          f[i][1][0][1] = max(f[i - 1][1][0][1], f[i - 1][1][0][0]) + s[i];
    51          f[i][1][1][1] = Max(f[i - 1][1][0][0], f[i - 1][1][1][1] + s[i], f[i - 1][1][0][1]);
    52          f[i][0][0][1] = max(f[i - 1][0][0][0], f[i - 1][0][0][1]) + s[i];
    53          f[i][0][1][1] = Max(f[i - 1][0][1][1] + s[i], f[i - 1][0][0][0], f[i - 1][0][0][1]);
    54          f[i][0][0][2] = max(f[i - 1][0][0][1], f[i - 1][0][0][2]);
    55          f[i][1][1][2] = Max_(f[i - 1][1][1][2], f[i - 1][1][1][1], f[i - 1][0][1][2] + s[i], f[i - 1][0][1][1] + s[i]);
    56          f[i][0][1][2] = max(f[i - 1][0][1][2], f[i - 1][0][1][1]);
    57     }
    58     printf("%lld
    ", Max_(f[n][1][1][2], f[n][1][1][1], f[n][0][0][2], f[n][0][0][1]));
    59 }
    60 
    61 int main()
    62 {
    63     freopen("in.in", "r", stdin);
    64     pre();
    65     work();
    66     fclose(stdin);
    67     return 0;
    68 }
    View Code
  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9788450.html
Copyright © 2011-2022 走看看