动态规划典型例题

来源:互联网 发布:企鹅听书软件 编辑:程序博客网 时间:2024/09/21 09:04

ykc想吃好吃的

题目描述

一天,ykc在学校闲的无聊,于是决定上街买点吃的,ykc很懒,本来就不是很像逛街,于是找来了czl帮他买,这里应该有滑稽,而czl也不愿为ykc买东西吃,但是ykc很强势,非让他去买,呢没办法了,然而czl还有很多事要做,没呢么多时间帮ykc,而这条小吃街又很长,有n家店,n有50000这么大,并且这n家店的商品价值有所不同(要知道,商品的价值可能为负,哈哈,很神奇吧,但是czl肯定不会傻到赔钱,所以你懂的),哇,czl要疯了,他不想逛这么久啊,他还有个毛病,他只会连续的逛若干家店,并且由于这条街的店很多,所以肯定不会是一条直线,换句话说就是首尾相连,即第n家店和第一家店是连在一起的,然而ykc希望czl买的东西价值最大,不然就会不开心,于是他就把艰难的任务交给你了,他真的不想浪费时间,你能帮助他吗?

输入

第1行:小吃街的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数,代表每个店的商品价值 (-10^9 <= S[i] <= 10^9)

输出

czl能买到的最大价值

样例输入

6-2 11 -4 13 5 -2

样例输出

25
本题考查的知识点是最大子序列和,不同的是数是首尾相连的,也就循环的数。
首先我们先讨论一下不循环的一大串数:
        最大和一定是某一段数相加,其中里面可能有负数,那我们就依次求和,两者取最大值就可以了
代码如下:
    
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int MAX=1e3+10;int a[MAX];int main(){       int n ;     while(~scanf("%d",&n))     {       for(int i = 0; i < n ; i++)               scanf("%d",&a[i]);       int sum = 0 ,ans=0; for(int i = 0; i < n; i++)      {          sum += a[i];          if(sum < 0)           sum = 0;           ans = max(ans , sum);  }     printf("%d\n",ans);           }return 0;}

如果是循环的数呢,那么最大和会在中间或两头出现;出现在中间时,上述代码就能解决。
如果出现在两头呢?
    反过来想一下,如果最大和出现在两边,那么最小和一定会出现在中间,那我们就可以用上述代码求最小和,用整个数的和减去最小和就会产生最大和,然后和中间的最大和进行比较,取最大即可。

代码如下:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int MAX=1e3+10;int a[MAX];int main(){       int n ;     while(~scanf("%d",&n))     {       for(int i = 0; i < n ; i++)               scanf("%d",&a[i]);       int sum = 0, sum1=0,sum2=0,ans = 0 ,ans1 = 0 ,ans2 = 0 ; for(int i = 0; i < n; i++)      {          sum += a[i];          sum1 += a[i];          sum2 += a[i];          if(sum1 < 0)              sum1 = 0;              if(sum2 > 0)                 sum2 = 0;               ans1 = max(ans1 , sum1);               ans2 = min(ans2,sum2);  }     printf("%d\n",max(ans1, sum-ans2));           }return 0;}

AC代码:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int MAX=5e4+10;long long int a[MAX];int main(){       long long int n ;     while(~scanf("%lld",&n))     {       for( int i = 0; i < n ; i++)               scanf("%lld",&a[i]);       long long int sum = 0, sum1=0,sum2=0 ,ans1 = 0 ,ans2 = 0 ; for(int i = 0; i < n; i++)      {          sum += a[i];          sum1 += a[i];           ans1 = max(ans1 , sum1);          sum2 += a[i];           ans2 = min(ans2,sum2);          if(sum1 < 0)              sum1 = 0;              if(sum2 > 0)                  sum2 = 0;                 }     printf("%lld\n",max(ans1, sum-ans2));           }return 0;}




原创粉丝点击