求数组(连续)在某一区间最大值(简单的动态规划的思想)

举个例子:9  -18 3 2 7 1在求这串维数组(连续)区间的最大值的时候,最开始的想法就是暴力,把每个区间的数都加在一起,然后再比较出最大的数,这种方法虽然可以做出来,但是太浪费时间了,所以就有了一个比较简单的想法动态规划的思想。先整一段代码瞅瞅:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int main(){
    int n;
    int a[100];
    while(~scanf("%d", &n)){
        int i, sum = 0;//sum用来记录某个区间的和
        for(i = 0; i < n; i++){
            cin>>a[i];
        }
        int max1 = 0;//如果区间全为负的情况下,使max1 = -999999,因为当全为负的情况下
        //更新的结果是最大的负数
        for(i = 0; i < n; i++){
            sum += a[i];
            max1 = max(sum, max1);//max1进行更新最大值,用max1来记录该点出现过的最大值。
            if(sum < 0)sum = 0;//如果该位置小于0的话,那就重新开始,
            //这个语句最好放在句尾,如果全为负,这么才能更新到最大的负数

        }
        cout<<max1<<endl;
    }
return 0;
}
//9  -18 3 2 7 1
//最快开始max1 = 0,然后sum = 9 > 0 max1 更新为 9
//sum = -9 < 0,sum 设置为0,max1不进行更新还是 9;
//sum= 3 > 0, sum < max1,max1不进行更新还是 9;
//sum =  5 > 0, sum < max1; max1不进行更新还是 9;
//sum = 12 > 0; sum > max1; max1进行更新更新为 12;
//sum = 13 > 0; sum > max1; max1进行更新更新为 13;
//最后输出max1,max1就是区间最大值

动态规划的思想就是从头开始累加,如果结果小于0,就把记录累加结果的值置为0,与此同时用一个数记录出现的最大结果,这个就是动态规划的思想了。下面是一道例题:

Problem 2253 Salty Fish

链接:http://acm.fzu.edu.cn/problem.php?pid=2253

这题就是咸鱼翻身,意思就是在某一区间对区间是0的数给翻过来,只能一次,求出最后有几条咸鱼翻身。

这题的想法就是先统计出有多少条鱼已经翻身了,然后把1置为-1,把0置为1,求出这个数组区间的最大值,也就是之前讲的思想,加上之前的和,就是结果。为什么这么做就可以了,因为你想把0置为1,但是你之前有的1,你是不想动的,但是你只要动了,你最原始的1,就相当于减少了,所以是-1,0置为1,相当于之前的数增加了。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int a[100001], b[100001];
int main(){
    int n, i;
    while(~scanf("%d", &n)){
        int sum = 0;
        for(i = 0; i < n; i++){
                scanf("%d", &a[i]);
                if(a[i] == 1)b[i] = -1;
                else b[i] = 1;
                sum += a[i];
        }
        if(sum == n)
        {
        printf("%d\n",n-1);
        continue;
        }//至少翻转一条鱼,所以当全为1的时候总数减1
        int max1 = 0, c = 0;
        for(i = 0; i < n; i++){//连续区间求最大的值;
            c += b[i];
            if(c < 0)c = 0;
            max1 = max(c, max1);
        }

        printf("%d\n",max1+sum);


    }
return 0;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值