动态规划-最大子串 HDOJ1003

来源:互联网 发布:股票基本面软件 编辑:程序博客网 时间:2024/06/05 03:25

题目大意:输入是具有n个整数的向量x,输出是输入向量的任何联系子向量中的最大和,并输出该子向量的开始和结束为止。例如:

输入:

5 6 -1 5 4 -7

7 0 6 -1 1 -6 7 -5

输出:

Case 1:14 1 4

Case 2:7 1 6

分别有四种方法都能够求解出来分别是O(n^3)和O(n^2)以及O(n)但是只有分治算法和扫描算法能够AC,前两种都会超时。《编程珠玑》里面在第八章讲这个问题时有一句经典的话:任何正确的算法都必须至少花费O(n)的时间,所以最后的扫描算法已经很高效了,不需要优化了。


扫描算法代码如下复杂度O(N):

//time:328MS  mem:548k#include <iostream>using namespace std;int main(){    int T;    cin>>T;    short a[100002];    for(int k=1;k<=T;k++)    {        int n,locl,locr,max,ssum;        cin>>n;        for(int i=1;i<=n;i++)            cin>>a[i];        max = a[1];        ssum = 0;        locl = 1;        locr = 1;        int temp = 1;        for(int i=1;i<=n;i++)        {            ssum += a[i];                        if(ssum>max)            {                max = ssum;                locl = temp;                locr = i;            }            if(ssum<0)            {                ssum = 0;                temp = i+1;            }        }        cout<<"Case "<<k<<":"<<endl;        cout<<max<<" "<<locl<<" "<<locr<<endl;        if(k<=T-1)            cout<<endl;    }    return 0;}

平法算法(O(n^2)运行时会超时:

#include <iostream>using namespace std;int main(){    int T;    cin>>T;    short a[100002];    short sum[100002];    for(int k=1;k<=T;k++)    {        int n;        cin>>n;        for(int i=1; i<=n; i++)        {            cin>>a[i];        }        sum[0]=0;        sum[1] = a[1];        for(int j=2; j<=n;j++)            sum[j] = a[j]+sum[j-1];                int max = a[0];        int ssum;        int locl=0,locr=0;        for(int i=1;i<=n;i++)        {            for(int j=i;j<=n;j++)            {                ssum = sum[j]-sum[i-1];                if(ssum>max)                {                    max = ssum;                    locl = i;                    locr = j;                }            }        }        cout<<"Case "<<k<<":"<<endl;        cout<<max<<" "<<locl<<" "<<locr<<endl;    }    return 0;}




原创粉丝点击