1052 最大m子段和
基準時間限制:2 秒 空間限制:131072 kb 分值: 80 難度:5級演算法題
n個整數組成的序列a[1],a[2],a[3],…,a[n],將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m >= n個數中正數的個數,那麼輸出所有正數的和。
例如:-2 11 -4 13 -5 6 -2,分為2段,11 -4 13一段,6一段,和為26。
input
第1行:2個數n和m,中間用空格分隔。n為整數的個數,m為劃分為多少段。(2 <= n , m <= 5000)output第2 - n+1行:n個整數 (-10^9 <= a[i] <= 10^9)
輸出這個最大和input示例
7 2output示例-211
-413-56
-2
26//題意有點難懂,應該是說,從 n 個數中,選出小於等於 m 段,不相交,並且和最大
顯然dp題,但怎麼設計比較難,假設劃分成 x 段,對於每個元素,有這樣的考慮,
1、和上乙個連起來,就是上乙個位置分為 x 段
2、或者新開一段,就是上乙個位置分 x-1 段
那麼, dp[i][j] 表示前 i 個數選出 j 段,並且最後一段有 dat[i]
dp[i][j] = max(dp[i-1][j] , dp[j-1 -- i-1][j-1])
然後發現這是 n^3 ,得優化一下
dp[j-1 -- i-1][j-1] 這個可以用乙個陣列存一下,
設為 pre[i][j] ,表 前 i 個數,選出 j 段的最大和
pre[i][j] = max(pre[i-1][j],dp[i][j])
然後可以發現,最多和 j-1 有關,所以可以滾動一下優化空間,就可以愉快的dp辣
1 #include 2view codeusing
namespace
std;
3#define mod 1000000007
4#define inf 0x3f3f3f3f
5#define eps 1e-9
6#define ll long long
7#define mx 500589
intn,k;
10int
dat[mx];
11 ll dp[mx][2
];12 ll pre[mx][2
];13
14int
main()
1525 ll ans =0;26
for (int j=1;j<=k;j++)
2733 ans = max(ans,pre[n][j&1
]);34
}35 printf("
%lld\n
",ans);36}
37return0;
38 }
1052 最大M子段和 (dp)
n個整數組成的序列a 1 a 2 a 3 a n 將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m n個數中正數的個數,那麼輸出所有正數的和。例如 2 11 4 13 5 6 2,分為2段,11 4 13一段,6一段,和為26。input 第1行 2個數n和m,中間用空格分隔。...
51nod 1052 最大M子段和 DP
題目傳送門 好吧,好像是我zz了,原來連續的一段數可以當做許多段數來看的 突然掀桌,氣得我都變成簡筆畫了!害得我wa了6發!其實這題就是一道非常水的dp題,定義f i j 0 1 表示前 i 個數選了 j段,第三維表示當前的數是否被選在第 j 段數內。然後直接進行狀態轉移就行了。突然發現這樣開陣列會...
51Nod 1052 最大M子段和 DP
第一眼dp 第二眼隔板法 第三眼。嗯?第二眼好像看偏了?重新看第二眼 二維dp 所以說這道題是看兩眼就可以看出來做法的比較裸的dp題 wa了一發以後又重新看了一眼題面 嗯,要開long long 所以說這道題是看三眼就可以ac的比較裸的dp題 做完後倒回來看一眼自己的程式 嗯,只用到前面的一維 陣列...