zoukankan      html  css  js  c++  java
  • 环状最大两段子段和

    深感人类智慧的伟大啊,,,

    第一次看这题简直毫无头绪,

    其实状态设出来了,往下推就顺理成章了。

    f[i][j][k]表示到第i位,选了j段,第i位有没有选(k)的最大子段和,

    然后考虑用人类智慧暴力推倒所有情况的转移方程,

    f[i][1][1]:因为要取第i位,又只有一段,所以要么接这上一段来,要么就是新的一段

    于是有:f[i][1][1]=max(s[i],f[i-1][1][1]);

    f[i][1][0]:因为第i位不取,所以对前面的那一段也就没上面限制了

    于是有:f[i][1][0]=max(f[i-1][1][1],f[i-1][1][0]);

    f[i][2][0]:因为第i为不取,所以同理,

    有 f[i][2][0]=max(f[i-1][2][0],f[i-1][2][1]);

    f[i][2][1]:因为要取第i位,所以如果前面就有两段的话,上一位必须取,否则就有3段了,如果前面只有一段,那么就没有限制,

    于是:f[i][2][1]=max(f[i-1][2][1],f[i-1][1][1],f[i-1][1][0]);

    那么显然这是没有考虑环的情况的,由于段数只有2段,因此我们还是可以暴力枚举情况解决。
    显然最大ans只可能由有环参与or没环参与两种情况得来(也没别的情况了)

    观察到一个性质,要是对ans的贡献利用到了环,那么有:

    第一个必须被选,最后一个也必须被选

    这种情况在序列上表现为:

    分了3段,其中第一段从第一个开始,最后一段以最后一个结束。

    因此我们只需要再DP一次考虑必须有环的情况即可,

    推式子的思路与上面类似,下面代码应该写的挺清楚的,可以自己先推一下

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 200100
     5 #define getchar() *o++
     6 char READ[2000100],*o=READ;
     7 int n,ans;
     8 int s[AC],f[AC][4][2];
     9 /*毕竟还是比较妙的,充分体会到了人类智慧的伟大,
    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 void work()
    31 {
    32     memset(f,128,sizeof(f));
    33     for(R i=1;i<=n;i++)
    34     {
    35         f[i][1][1]=max(s[i],f[i-1][1][1] + s[i]);
    36         f[i][1][0]=max(f[i-1][1][1],f[i-1][1][0]);
    37         if(i >= 2) 
    38         {    
    39             f[i][2][0]=max(f[i-1][2][0],f[i-1][2][1]);
    40             f[i][2][1]=max(f[i-1][2][1],max(f[i-1][1][0],f[i-1][1][1])) + s[i];
    41         }
    42     }
    43     ans=max(f[n][2][0],f[n][2][1]);
    44     memset(f,128,sizeof(f));//重新初始化
    45     //因为绕回来后在数列上的直接表现就是分成了3段,所以,,,
    46     //3段中第一段必须从第一个开始取,最后一段必须一直取到结尾
    47     f[1][1][1]=s[1];
    48     for(R i=2;i<=n;i++)
    49     {
    50         f[i][1][1]=f[i-1][1][1] + s[i];//要是只有一段,还取i的话,一定是取了一整段
    51         f[i][1][0]=max(f[i-1][1][0],f[i-1][1][1]);
    52         f[i][2][0]=max(f[i-1][2][1],f[i-1][2][0]);
    53         f[i][2][1]=max(f[i-1][2][1],max(f[i-1][1][1],f[i-1][1][0])) + s[i];//error。。。取了自己的都要把自己加上啊
    54         f[i][3][1]=max(f[i-1][3][1],max(f[i-1][2][1],f[i-1][2][0])) + s[i];//error!!!-1啊啊啊啊
    55         //printf("%d = %d %d %d %d %d
    ",i,f[i][1][0],f[i][1][1],f[i][2][0],f[i][2][1],f[i][3][1]);
    56     }
    57     ans=max(ans,f[n][3][1]);//因为绕回来了,所以最后一个必须取
    58     printf("%d
    ",ans);
    59 }
    60 
    61 int main()
    62 {
    63 //    freopen("in.in","r",stdin);
    64     fread(READ,1,2000000,stdin);
    65     pre();
    66     work();
    67 //    fclose(stdin);
    68     return 0;
    69 }
  • 相关阅读:
    Django(模板语言-自定义filter和simple_tag)
    vue项目创建步骤小结
    scrapy 相关
    face parsing(人脸解析)
    FSRNet: End-to-End Learning Face Super-Resolution with Facial Priors论文阅读
    第一周,深度学习的实用层面
    如何阅读英文文献
    学习笔记
    Joint Super-Resolution and Alignment of Tiny Faces
    Super-FAN:Integrated facial landmark localization and super-resolution of real-world low resolution faces in arbitrary poses with GANs论文阅读
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9040480.html
Copyright © 2011-2022 走看看