hud 1003 max sum 算法导论学习

题意:找出数列中最大子数列,如果有多个则输出第一个

分治法:对于一个数组a[low..high]:最大子数组a[i...j]必然所处的位置是一下三个情况之一:

1.完全位于子数组a[low..mid]中,因此low<=I<=j<=mid。

2.完全位于子数组a[mid+1...high]中,因此mid<I<=j<=high。

3.跨越了中点,因此low<=I<=mid<j<=high

对于一个数组a[low...high],求出跨越中点的最大子数组,分解为两个子数组:a[low..mid]  a[mid+1..high] ,分别求出它们的最大子数组,去其中大的为a[low...high]的最大子数组;

#include<iostream>
#include<limits.h>
using namespace std;
const int N=100000;
int a[N];
struct array{
    int left_max;
    int right_max;
    int sum;
    array(int a,int b,int c){
        left_max = a;
        right_max =b;
        sum = c;
    };
    array(){
        left_max = 0;
        right_max =0;
        sum = 0;
    };
};
array crossp(int *a,int low,int mid,int high)
{
    int lmax=INT_MIN,rmax=INT_MIN;
    int sum=0,lmaxpos=0,rmaxpos=0;
    for(int i=mid;i>=low;i--)
    {
        sum+=a[i];
        if(sum>=lmax)
        {
            lmax=sum;
            lmaxpos = i;
        }
    }
    sum=0;
    for(int i=mid+1;i<=high;i++)
    {
        sum+=a[i];
        if(sum>=rmax)
        {
            rmax=sum;
            rmaxpos = i;
        }
    }
    return array(lmaxpos,rmaxpos,lmax+rmax);
}
array find_max(int *a,int low,int high)
{
    array l,r,m; 
    if(low==high)return array(low,high,a[low]);
    else
    {
        int mid = (low+high)/2;
        l = find_max(a,low,mid);
        r = find_max(a,mid+1,high);
        m = crossp(a,low,mid,high);
        if(m.sum>=l.sum&&m.sum>=r.sum)return m;
        else if(l.sum>=r.sum&&l.sum>=m.sum)return l;
        else if(r.sum>=l.sum&&r.sum>=m.sum) return r;
        
    }
}
int main()
{
    int t,num;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        cin>>num;
        for(int i=0;i<num;i++)
        cin>>a[i];
        array c;
        c = find_max(a,0,num-1);
        cout<<"Case "<<i+1<<":"<<endl<<c.sum<<" "<<c.left_max+1<<" "<<c.right_max+1<<endl;
        if(i!=t-1)cout<<endl;
    }
}


做法二:动态规划

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define ll long long
using namespace std;
const int INF = ( 2e9 ) + 2;
const ll maxn = 100010;
int a[maxn];
int main()
{
	int T;
	scanf("%d",&T);
	for(int cas=1;cas<=T;cas++)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
		int sum=0,ans=0;
		int l=1,r=1,x=1;
		ans=sum=a[1];
		for(int i=2;i<=n;i++)
		{
			if(sum+a[i]<a[i])
			{
				sum=a[i];
				x=i;
			}
			else
			sum+=a[i];
			if(ans<sum) //更新答案 
			{
				l=x;
				r=i;
				ans=sum;
			}
		}
		if(cas!=1)puts("");
		printf("Case %d:\n%d %d %d\n",cas,ans,l,r);
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值