题解 P1281 【书的复制】
一个区间
\rm{OxO1} 前言
事实上,如果按照常规思路的话……这个题应该是一个
#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 600
struct range{
int L, R, Len ;
}r[MAXN] ; int Max ;
using namespace std ; int i, j, k, t ; stack <int > s ;
int N, M, base[MAXN], S[MAXN], F[MAXN][MAXN], dp[MAXN][MAXN] ;
inline void update(int x){
r[x].Len = S[r[x].R] - S[r[x].L - 1] ;
}
inline void dfs(int E){
for (int ii = 1 ; ii < E ; ++ ii){
int mark = 0 ;
while (r[ii].Len <= Max && r[ii + 1].Len <= Max && r[ii].L < r[ii].R)
r[ii].R --, r[ii + 1].L --, update(ii), update(ii + 1), mark ++ ;
if (r[ii + 1].Len > Max)
mark --, r[ii].R ++, r[ii + 1].L ++, update(ii), update(ii + 1) ;
if (mark) dfs(E - 1) ;
}
}
int main(){
memset(dp, 63, sizeof(dp)) ;
cin >> N >> M ; dp[0][0] = 0 ;
for (i = 1 ; i <= N ; ++ i)
cin >> base[i], S[i] = S[i - 1] + base[i] ;
for (i = 1 ; i <= N ; ++ i)
for (j = 1 ; j <= M ; ++ j)
for (k = 0 ; k < i ; ++ k){
if (dp[i][j] > (t = max(dp[k][j - 1], S[i] - S[k])))
dp[i][j] = t, F[i][j] = k + 1 ;
}
Max = dp[N][M], t = N, i = M, k = 0, j = 0 ;
while (F[t][i]) s.push(t), t = ((1 & k)) ? t - 1 : F[t][i], i = ((1 & k)) ? i - 1 : i, ++ k ;
while (1){
if (!s.empty()) r[++ j].L = s.top(), s.pop() ;
if (!s.empty()) r[j].R = s.top(), s.pop() ; else break ; update(j) ;
}
dfs(j) ;
/*for (i = 1 ; i < j ; ++ i){
while (r[i].Len <= Max && r[i + 1].Len <= Max && r[i].L < r[i].R) {
r[i].R --, r[i + 1].L --, update(i), update(i + 1) ;
}
if (r[i + 1].Len > Max) r[i].R ++, r[i + 1].L ++, update(i), update(i + 1) ;
}*/
for (i = 1 ; i <= j ; ++ i) cout << r[i].L << " " << r[i].R << endl ;
}