題目大意:輸入是具有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;
}