是的考试的时候这道题我又爆掉了….
这道题不难但是我考试的时候边界条件写错了只有40分…..
很简单的一个状态设定:
DP[I][J]
D
P
[
I
]
[
J
]
表示每一边的前
I
I
个一共划分成了个小区,那么很容易得到一个状态转移方程:
DP(I,K)=max(DP(I,K),DP(J,K−1)+fabs((Sum1[I]−Sum1[J])−(Sum2[I]−Sum2[J])))
D
P
(
I
,
K
)
=
m
a
x
(
D
P
(
I
,
K
)
,
D
P
(
J
,
K
−
1
)
+
f
a
b
s
(
(
S
u
m
1
[
I
]
−
S
u
m
1
[
J
]
)
−
(
S
u
m
2
[
I
]
−
S
u
m
2
[
J
]
)
)
)
其中 Sum1 S u m 1 表示 A[] A [ ] 的前缀和, Sum2 S u m 2 表示 B[] B [ ] 的前缀和。
然后写代码的时候注意一下边界条件…..吸取教训吧….
参考代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define DP(A,B) DP[A][B]
using namespace std;
const int Max=1e3+5;
const int Mod=1e9+7;
int N,M;
DB Sum1[Max],Sum2[Max],A[Max],B[Max],DP[Max][Max];
int main(){
int I,J,K;
//freopen("dis.in","r",stdin);
//freopen("dis.out","w",stdout);
scanf("%d%d",&N,&M);
for(I=1;I<=N;I++){
scanf("%lf",&A[I]);
Sum1[I]=Sum1[I-1]+A[I];
}
for(I=1;I<=N;I++){
scanf("%lf",&B[I]);
Sum2[I]=Sum2[I-1]+B[I];
}
for(I=1;I<=N;I++){
DP(I,1)=fabs(Sum1[I]-Sum2[I]);
for(K=2;K<=min(I,M);K++){
for(J=K-1;J<=I;J++){
DP(I,K)=max(DP(I,K),DP(J,K-1)+fabs((Sum1[I]-Sum1[J])-(Sum2[I]-Sum2[J])));
}
}
}
printf("%.6lf",DP[N][M]);
return 0;
}