31 -41 59 26 -53 58 97 -93 -23 84
子矩陣59+26-53+58+97=187爲所求的最大子數組。
題目很短,如果沒有時間限制的話,窮舉大法確實簡單,但是有時間限制,只能用dp大法啦
思想:
- 令b[j]表示以位置 j 爲終點的所有子區間中和最大的一個
- 子問題:如j爲終點的最大子區間包含了位置j-1,則以j-1爲終點的最大子區間必然包括在其中
- 如果b[j-1] >0, 那麼顯然b[j] = b[j-1] + a[j],用之前最大的一個加上a[j]即可,因爲a[j]必須包含
- 如果b[j-1]<=0,那麼b[j] = a[j] ,因爲既然最大,前面的負數必然不能使你更大
#include<stdio.h>
#include<cmath>
#include<iostream>
#include<map>
#include<string.h>
#define maxn 500
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int map[maxn][maxn];
bool vis[maxn][maxn];
int b[maxn];
int a[maxn];
int ans;
int main()
{
int n;
while(cin>>n)
{
mem(b,0);
mem(a,0);
for(int i=1; i<=n; i++)
{
cin>>a[i];
}
int sum=0;
for(int i=1; i<=n; i++)
{//核心代碼:
if(b[i-1]>0)
{
b[i]=b[i-1]+a[i];
}
else
{
b[i]=a[i];
}
}
for(int i=1; i<=n; i++)
{
if(b[i]>sum)
sum=b[i];
}
printf("%d\n",sum);
}
return 0;
}
窮舉大法就寫個大佬的代碼吧:
直接窮舉法o(n^3):
int
start = 0;
int
end = 0;
int
max = 0;
for
(
int
i = 1; i <= n; ++i)
{
for
(
int
j = i; j <= n;++j)
{
int
sum = 0;
for
(
int
k = i; k <=j; ++k)
sum += a[k];
if
(sum > max)
{
start = i;
end = j;
max = sum;
}
}
}
帶記憶的遞推法(比直接窮舉快了不少)(o(n^2)):
int
start = 0;
int
end = 0;
int
max = 0;
for
(
int
i = 1; i <= n; ++i)
{
int
sum = 0;
for
(
int
j = i; j <= n;++j)
{
sum += a[j];
if
(sum > max)
{
start = i;
end = j;
max = sum;
}
}
}