zoukankan      html  css  js  c++  java
  • [noip模拟赛]某种数列问题<dp>

    某种数列问题  (jx.cpp/c/pas) 1000MS 256MB

    众所周知,chenzeyu97有无数的妹子(阿掉!>_<),而且他还有很多恶趣味的问题,继上次纠结于一排妹子的排法以后,今天他有非(chi)常(bao)认(cheng)真(zhe)去研究一个奇怪的问题。有一堆他的妹子站成一排,然后对于每个妹子有一个美丽度,当然美丽度越大越好,chenzeyu97妹子很多,但是质量上不容乐观,经常出现很多美丽度为负数的妹子(喜闻乐见),chenzeyu97希望从一排妹子里找出3队连续的妹子,使她们的美丽度和最大。注意,一个妹子不能被编入多个队伍而且一定要拿出三队,不然czy会闲着没事做~。

    简单滴说就是:

    给定一个数列,从中找到3个无交集的连续子数列使其和最大。

    【输入文件】

    第一行一个数n,表示数列长度。

    接下来有n行,每行一个数,第i行为第i个数。

    【输出文件】

    仅有一个数,表示最大和。

    【样例输入】 jx.in

    10

    -1

    2

    3

    -4

    0

    1

    -6

    -1

    1

    -2

    【样例输出】 jx.out

    7

    【样例说明】

    第一队妹子取2,3。

    第二队妹子取0,1。

    第三队妹子取1。

    【数据范围】

    请大家放心,虽然chenzeyu97妹子无数,但是这次他叫来的个数n是有限的。=v=

    对于30%的数据,妹子数不大于200。

    对于60%的数据,妹子数不大于2000。

    对于100%的数据,妹子数1000000。

    前几天考了这套题,唯一A了的就是这道题,但是还是感觉自己的dp能力很捉鸡啊!

    这题的思路不难,就是一个三维数组可以解决的事情,我们定义数组dp[i][j][k],然后j表示在前i个数中选出j端区间,k只有0和1,0表示不选,1表示要选;

    dp[i][j][0]表示在前i个数选j个区间,但是第i个数不选;dp[i][j][1]表示在前i个数选j个区间,但是一定要选第i个数

    知道了这个,其实代码就明了了,对于每一个dp[i][j],值就是来自dp[i][j][0],dp[i][j][1]两者的最大值;

    dp[i][j][0]的来源是前i-1个数选j个区间,不过是选不选第i-1的区别

    dp[i][j][1]的来源是前i-1个数中是分为j个区间还是j-1个区间的区别,不过在分成j-1个区间是还要考虑选不选第i-1个

    然后就可以推出答案所在的位置:max(dp[n][3][1],dp[n][3][0]);

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<queue>
     8 #define maxn 1000005
     9 using namespace std;
    10 
    11 int n,a[maxn],sum;
    12 int dp[maxn][5][2];
    13 //前i个选j个无交集区间,0表示不取i,1表示要取i 
    14 int main()
    15 {
    16     freopen("jx.in","r",stdin);
    17     freopen("jx.out","w",stdout);
    18     scanf("%d",&n);
    19     for(int i=1;i<=n;i++)
    20     {
    21         scanf("%d",&a[i]);
    22         sum+=a[i];
    23     }
    24     if(n<=3){printf("%d",sum);return 0;}    
    25     for(int i=1;i<=n;i++)
    26      for(int j=1;j<=3;j++)
    27      {
    28          dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]);
    29          //不取i的话,就在前i-1个数选j个区段,对于i-1选或者不选 
    30          dp[i][j][1]=max(max(dp[i-1][j-1][0],dp[i-1][j-1][1]),dp[i-1][j][1])+a[i];
    31          //选了i,就看选不选第i-1个数,选的话,是和i一个区段还是在另一个区段 
    32      }
    33     printf("%d",max(dp[n][3][0],dp[n][3][1]));
    34 }
    View Code
  • 相关阅读:
    这是另外一篇
    使用客户端写博客
    vim编码相关配置
    给eclipse装一些插件
    手机型号收集
    解决黑苹果与windows时区不一致
    记录一些在VPS上折腾的东西
    一个获取文件绝对路径的sh
    python批量GBK转UTF-8
    用NDK编译lua库
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7469798.html
Copyright © 2011-2022 走看看