• 最大子数组


    Max Sum

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 120366    Accepted Submission(s): 27835


    Problem Description
    Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
     


    Input
    The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
     


    Output
    For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
     


    Sample Input
    2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5
     


    Sample Output
    Case 1: 14 1 4 Case 2: 7 1 6

    这个是我根据算法导论上写的,大牛们如果看到了请指点一下这个下标该怎么求!!!

     --我已经自己改正了,仅仅改成结构体就可以了!

    //最大子数组之和正确,但是下标不正确!!!
    /*
    测试用例:
    9
    13 1 2 3 -100 1 2 3 -100 1 2 1 1 1
    5 -3 -2 -1 -2 -3 
    正确结果:
    Case 1: 6 9 13
    —— -1 3 3
    */
    #include<iostream>
    #define MIN -1000000005
    using namespace std;
    
    int left_low,left_high,right_low,right_high,cross_low,cross_high,flg;
    
    int max(int a, int b){return a>b?a:b;}
    
    //求过中点的最大和
    int maxCenterSum(int *A, int low, int mid, int high)
    {
    	int left_sum=MIN,sum=0,right_sum=MIN;
    	int i,j;
    
    	for(i=mid;i>=low;i--)
    	{
    		sum=sum+A[i];
    		if(sum>=left_sum){left_sum=sum;cross_low=i;}
    	}
    	sum=0;
    	for(j=mid+1;j<=high;j++)
    	{
    		sum=sum+A[j];
    		if(sum>=right_sum){right_sum=sum;cross_high=j;}
    	}
    	return left_sum+right_sum;
    }
    
    //分别左右最大
    int maxSub(int *A, int low, int high)
    {
    	if(low==high)return A[low];
    	int mid=(low+high)>>1;
    	
    	int left_sum,right_sum,cross_sum;
    
    	left_sum = maxSub(A, low, mid);
    	
    	right_sum= maxSub(A, mid+1, high);
    	
    	cross_sum= maxCenterSum(A, low, mid, high);
    
    	/*return max(left_sum, max(right_sum, cross_sum));*/
    	if(left_sum>=cross_sum && left_sum>=right_sum){flg=1;left_low=low;left_high=mid;return left_sum;}
    	else if(right_sum>=left_sum && right_sum>=cross_sum){flg=3;right_low=mid+1;right_high=high; return right_sum;}
    	else {flg=2;return cross_sum;}
    }
    
    int main()
    {
    	int T,i,n,cnt;
    	int ans,a[100001],l,r;
    	cin>>T;
    	cnt=0;
    	while(cnt<T)
    	{
    		flg=0;
    		left_low=0;left_high=0;
    		right_low=0;right_high=0;
    		cross_low=0;cross_high=0;
    		cnt++;
    		cin>>n;
    		for(i=1;i<=n;i++)
    			cin>>a[i];
    		ans = maxSub(a, 1, n);
    		cout<<"Case "<<cnt<<":"<<endl<<ans<<" ";
    		if(flg==0)cout<<"1 1"<<endl;
    		else if(flg==1)cout<<left_low<<" "<<left_high<<endl;
    		else if(flg==2)cout<<cross_low<<" "<<cross_high<<endl;
    		else cout<<right_low<<" "<<right_high<<endl;
    		if(cnt!=T)cout<<flg<<endl;
    	}
    	system("pause");
    	return 0;
    }
    

      

    //这个是改正了的!
    //分治思想
    /*
    测试用例:
    9
    13 1 2 3 -100 1 2 3 -100 1 2 1 1 1
    5 -3 -2 -1 -2 -3 
    正确结果:
    Case 1: 6 9 13
    —— -1 3 3
    */
    #include<iostream>
    #define MIN -1000000005
    using namespace std;
    
    struct set
    {
    	int sum,begin,end;
    };
    
    //int left_low,left_high,right_low,right_high,cross_low,cross_high,flg;
    
    set max(set a, set b){return a.sum>b.sum ? a:b;}
    
    //求过中点的最大和
    set maxCenterSum(int *A, int low, int mid, int high)
    {
    	int left_sum=MIN,sum=0,right_sum=MIN;
    	int i,j;
    	set cent;
    	for(i=mid;i>=low;i--)
    	{
    		sum=sum+A[i];
    		if(sum>=left_sum){left_sum=sum;cent.begin=i;}
    	}
    	sum=0;
    	for(j=mid+1;j<=high;j++)
    	{
    		sum=sum+A[j];
    		if(sum>=right_sum){right_sum=sum;cent.end=j;}
    	}
    	cent.sum = left_sum+right_sum;
    	return cent;
    }
    
    //分别左右最大
    set maxSub(int *A, int low, int high)
    {
    	set lcr;
    
    	if(low==high){lcr.sum = A[low];lcr.begin=low;lcr.end=low;return lcr;}
    	int mid=(low+high)>>1;
    
    	set left_sum,right_sum,cross_sum;
    
    	left_sum.begin=low;left_sum.end=mid;
    	left_sum = maxSub(A, low, mid);
    
    	right_sum.begin=mid+1;right_sum.end=high;
    	right_sum= maxSub(A, mid+1, high);
    
    	cross_sum= maxCenterSum(A, low, mid, high);
    
    	return max(left_sum, max(right_sum, cross_sum));
    }
    
    int main()
    {
    	int T,i,n,cnt;
    	int a[100001],l,r;
    	set ans;
    	cin>>T;
    	cnt=0;
    	while(cnt<T)
    	{
    		cnt++;
    		cin>>n;
    		for(i=1;i<=n;i++)
    			cin>>a[i];
    		ans = maxSub(a, 1, n);
    		cout<<"Case "<<cnt<<":"<<endl<<ans.sum<<" ";
    		cout<<ans.begin<<" "<<ans.end<<endl;
    		if(cnt!=T)cout<<endl;
    	}
    	/*system("pause");*/
    	return 0;
    }
    

      体会:还是应该善用结构体,像递归这种题不可能将所有结果仅仅保存在同一个int或其他类型下,必须要利用结构体。

         这种求最大子数组的问题,不便于用分治算法做,而应该用动态规划。分治的时间复杂度为nlgn,而动规的仅为n。

    世上无难事,只要肯登攀。
  • 相关阅读:
    day 66 crm(3) 自创组件stark界面展示数据
    day 65 crm(2) admin源码解析,以及简单的仿造admin组件
    用 Python+nginx+django 打造在线家庭影院
    django -admin 源码解析
    day 64 crm项目(1) admin组件的初识别以及应用
    云链接 接口不允许 情况 解决方法 mysql Host is not allowed to connect to this MySQL server解决方法
    day 56 linux的安装python3 ,虚拟环境,mysql ,redis
    day55 linux 基础以及系统优化
    Codeforces 989 P循环节01构造 ABCD连通块构造 思维对云遮月参考系坐标轴转换
    Codeforces 990 调和级数路灯贪心暴力 DFS生成树两子树差调水 GCD树连通块暴力
  • 原文地址:https://www.cnblogs.com/littlehoom/p/3427256.html
Copyright © 2020-2023  润新知