zoukankan      html  css  js  c++  java
  • [DP]最大连续子序列-hdu 1231

    题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1231

    算法参考:http://blog.163.com/wuguojin03@126/blog/static/17154113120109510946717/

    状态:dp[i]:以i为结尾的最大连续序列和
    初始状态:dp[i]=a[i]
    状态转移:dp[i]=max{dp[i-1]+a[i],a[i]}
    要求最大的,只需从dp[i]找出最大值就行了

    以本题输入样例 “ -2 11 -4 13 -5 -2 ” 为例:

    序号:  0   1   2   3   4   5
     a[]: -2  11  -4  13  -5  -2
    dp[]: -2  11   7  20  15  13

    观察dp[],终点即为 max:20,起点则为从max往前找最后一个不为负的数,即11

    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    
    const int N=10010;
    int a[N],dp[N];
    
    int main()
    {
        int n;
        while(cin>>n && n){
            int s=0,e=0;
            for (int i = 0; i < n; ++i){
                cin>>a[i];
                dp[i]=a[i];
            }
    
            for(int i=1;i<n;++i){
                dp[i]=max( dp[i-1]+a[i] , a[i] );
            }
    
            //查找最大和及终点
            int mymax=-1;
            for (int i = 0; i < n; ++i){
                if(mymax<dp[i]){
                    mymax=dp[i];
                    e=i;
                }
            }
            //查找起点
            for(int i=e;i>=0;--i)
                if(dp[i]<0){
                    s=i+1;
                    break;
                }
            if(mymax<0)cout<<"0 "<<dp[0]<<" "<<dp[n-1]<<endl;
            else cout<<mymax<<" "<<a[s]<<" "<<a[e]<<endl;
        }
        return 0;
    }
    

      

    一年后,偶遇此题又做一遍,用的是双dp,效率还没有上面的高:

    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    const int MAXN=10000+5;
    
    int a[MAXN],dp_l[MAXN],dp_r[MAXN];
    int n;
    
    int main()
    {
    	while(scanf("%d",&n)&&n>0)	{
    		for(int i=0;i<n;++i){
    			scanf("%d",&a[i]);
    		}
    
    		dp_l[0]=a[0];
    		dp_r[n-1]=a[n-1];
    		int ans=a[0],start=0,end=n-1;
    		for(int i=1;i<n;++i){
    			dp_l[i]=max(a[i],a[i]+dp_l[i-1]);
    			if(dp_l[i]>ans){
    				ans=dp_l[i];
    				end=i;
    			}
    		}
    		ans=a[0];
    		for(int i=n-2;i>=0;--i){
    			dp_r[i]=max(a[i],a[i]+dp_r[i+1]);
    			if(dp_r[i]>=ans){
    				ans=dp_r[i];
    				start=i;
    			}
    		}
    		
    		if(ans<0){
    			ans=0;start=0;end=n-1;
    		}
    		printf("%d %d %d
    ",ans,a[start],a[end] );
    	}
    	return 0;
    }
    

    还有一种方法,也挺快,不过不是用的动态规划:

    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    const int MAXN=10000+5;
    
    int a[MAXN],dp_l[MAXN],dp_r[MAXN];
    int n;
    
    int main()
    {
    	while(scanf("%d",&n)&&n>0)	{
    		for(int i=0;i<n;++i){
    			scanf("%d",&a[i]);
    		}
    		int start=0,end=n-1,left,ans=a[0],sum=0;
    		for(int i=0;i<n;++i){
    			if(sum<0) { //如果前几项和小于0,就重新开始记录
         			sum=0;
         			left=i; //刷新临时起点
         		}
         		sum+=a[i];        		
         		if(sum>ans){ //如果现在的sum大于原来的max,刷新数据
         			ans=sum;
         			start=left;
         			end=i;
         		}
    		}
    		
    		if(ans<0){
    			ans=0;start=0;end=n-1;
    		}
    		printf("%d %d %d
    ",ans,a[start],a[end] );
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    解读tensorflow之rnn 的示例 ptb_word_lm.py
    tensorflow 的rnn的示例 ptb_word_lm.py 的完整代码
    python中decorator的用法及原理(一)
    android 6 (API 23) 及更高版本 面向 NDK 开发者的 Android 变更
    GCC选项_-Wl,-soname 及 DT_NEEDED 的解释
    一万小时天才理论
    好好说话!
    如何打造你的独立观点
    整理的艺术3
    读过的书记不住怎么办?
  • 原文地址:https://www.cnblogs.com/bruce27/p/4247961.html
Copyright © 2011-2022 走看看