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
  • 相关阅读:
    request.getParameter() 和request.getAttribute() 区别
    Java中this和super的用法总结
    jQuery实现列表框双向选择操作
    Eclipse中.setting目录下文件介绍
    通过Ajax方式上传文件,使用FormData进行Ajax请求
    ASP.NET程序中常用的三十三种代码
    计算地球上两个坐标点(经度,纬度)之间距离sql函数
    动态调用WebService(C#) (非常实用)
    带SoapHeader验证的WebServices
    GridView内容详解(转载)
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9788450.html
Copyright © 2011-2022 走看看