題目大意:給出一串數字,求出子序列中的最大和。
思路:典型的dp問題,狀態轉移方程爲:dp[i]=max{dp[i-1],dp[i-1]+a[i]}.設置start和end兩個指標,用來記錄結果子序列中的開始和結束的位置。
值得注意的是這道題目中的格式要求很多,一開始沒太在意所以wrong answer 了好幾次。
如下是第一次AC的代碼:
# include <iostream>
# include <algorithm>
using namespace std;
int a[100005],dp[100005];
int main ()
{
int total,t;
int n,i,k,maxs,start,end;
scanf("%d",&total);
t=total;
while(t--)
{
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
dp[1]=a[1];
maxs=dp[1];
k=start=end=1;
for(i=2;i<=n;i++)
{
if((dp[i-1]+a[i])<a[i])
{
dp[i]=a[i];
k=i;
}
else
dp[i]=dp[i-1]+a[i];
if(dp[i]>maxs)
{
maxs=dp[i];
start=k;
end=i;
}
}
printf("%s%d:\n%d %d %d\n","Case ",total-t,maxs,start,end);
if(t)
printf("\n");
}
//system("pause");
return 0;
}
之後嘗試了下改進,代碼如下。因爲從上面的循環中可以看出,其實兩個數組並沒有什麼用,完全可以用一個變量來替代,這樣就需要在讀入數據的同時做處理,邊度數據,邊累加處理。
# include <iostream>
# include <algorithm>
using namespace std;
int main ()
{
int total,t;
int n,i,k,maxs,start,end,sum,a;
scanf("%d",&total);
t=total;
while(t--)
{
scanf("%d",&n);
scanf("%d",&a);
start=end=k=1;
maxs=sum=a;
for(i=2;i<=n;i++)
{
scanf("%d",&a);
sum=sum+a;
if(sum<a)
{
sum=a;
k=i;
}
if(maxs<sum)
{
maxs=sum;
start=k;
end=i;
}
}
printf("%s%d:\n%d %d %d\n","Case ",total-t,maxs,start,end);
if(t)
printf("\n");
}
system("pause");
return 0;
}