一条街道的两侧各连续坐落着 NN 座单元楼。现在要为这些单元楼划分居民校区。
规则如下:
每个小区只能由同一侧连续的若干座单元楼组成。且两侧都恰有 KK 个小区(每个小区至少有一栋楼)。
两侧的小区划分规则应该相同,比如,若左边的房子被分成 {1,2},{3}{1,2},{3} 这两个小区,那么右边也应该如此。
这样两边合计一共有 KK 对小区。
用 a_i,b_ia
i
,b
i
表示左右两边每座楼的人口在同侧所有单元楼总人口中所占的百分比,定义一个小区的相对拥挤程度为其人口百分比之和(左边就是对应 a_ia
i
的和,右边是对应 b_ib
i
的和)。定义这条街道的总拥挤程度为左右两边 KK 对小区的相对拥挤程度之差的绝对值之和。
现在,请你求出可能的最大拥挤程度。
输入格式
第一行两个整数 NN 和 kk。
第二行 NN 个实数,第 ii 个数为 a_ia
i
。
第三行 NN 个实数,第 ii 个数位 b_ib
i
。
输出格式
一个实数,表示这条街道的最大相对拥挤程度,保留到小数点后六位。
数据范围与约定
对于 30\%30% 的数据:n \le 20n≤20。
对于 100\%100% 的数据:n \le 800,k \le 80,k \le nn≤800,k≤80,k≤n。
保证 \sum a_i=1, \sum b_i=1∑a
i
=1,∑b
i
=1。
样例解释
11 号楼一个小区,(2,3)(2,3) 号楼 11 个小区。
这样相对拥挤程度最大为 abs(0.1 - 0.4) + abs(0.75 + 0.15 - (0.3 + 0.3))=0.6abs(0.1−0.4)+abs(0.75+0.15−(0.3+0.3))=0.6。
样例输入
3 2
0.1 0.75 0.15
0.4 0.3 0.3
样例输出
0.600000
题目来源
2017 NOIP 提高组模拟赛(三)Day2
昨天晚上的比赛,本来可以AC的,昨晚上最后只交了在网页上写的代码,本地AC代码没有交,直到现在题库里有了这道题,才A掉
//就是DP啦~
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 805
#define MAXK 85
double a[MAXN],b[MAXN],f[MAXN][MAXK];
int n,p;
inline void read(int &x){
x=0; char c=getchar(); int f=1;
while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;
}
int main(){
read(n),read(p);
for(int i=1;i<=n;++i) scanf("%lf",&a[i]),a[i]+=a[i-1];
for(int i=1;i<=n;++i) scanf("%lf",&b[i]),b[i]+=b[i-1];
for(int i=1;i<=n;++i){
f[i][1]=fabs(a[i]-b[i]);
for(int k=2;k<=i&&k<=p;++k)
for(int j=k-1;j<i;++j)
f[i][k]=max(f[i][k],f[j][k-1]+fabs((a[i]-a[j])-(b[i]-b[j])));
}
printf("%.6lf\n",f[n][p]);
return 0;
}