计蒜客NOIP模拟赛(3)D2T1 小区划分
一条街道的两侧各连续坐落着 N 座单元楼。现在要为这些单元楼划分居民校区。
规则如下:
-
每个小区只能由同一侧连续的若干座单元楼组成。且两侧都恰有 K 个小区(每个小区至少有一栋楼)。
-
两侧的小区划分规则应该相同,比如,若左边的房子被分成 {1,2},{3} 这两个小区,那么右边也应该如此。
这样两边合计一共有 K 对小区。
用 ai,bii,bi 表示左右两边每座楼的人口在同侧所有单元楼总人口中所占的百分比,定义一个小区的相对拥挤程度为其人口百分比之和(左边就是对应 aia_iai 的和,右边是对应 bib_ibi 的和)。定义这条街道的总拥挤程度为左右两边 KKK 对小区的相对拥挤程度之差的绝对值之和。
现在,请你求出可能的最大拥挤程度。
输入格式
第一行两个整数 N 和 k。
第二行 N 个实数,第 i 个数为 aii。
第三行 N 个实数,第 i 个数位 bii。
输出格式
一个实数,表示这条街道的最大相对拥挤程度,保留到小数点后六位。
数据范围与约定
对于 30%的数据:n≤20。
对于 100% 的数据:n≤800,k≤80。
保证 ∑ai=1,∑bi=111i=1,∑bi=1。
样例解释
1号楼一个小区,(2,3) 号楼 1个小区。
这样相对拥挤程度最大为 abs(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
dp水题
f[i][j]表示前i个楼,j个小区的最大值
dp方程式显然,因为数据不大
1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 double x[1000],y[1000],sx[1000],sy[1000]; 7 double f[1000][100]; 8 int n,k; 9 int main() 10 { 11 scanf("%d %d\n",&n,&k); 12 for (int i=1;i<=n;i++) 13 { 14 scanf("%lf",&x[i]); 15 sx[i]=sx[i-1]+x[i]; 16 } 17 for (int i=1;i<=n;i++) 18 { 19 scanf("%lf",&y[i]); 20 sy[i]=sy[i-1]+y[i]; 21 } 22 for (int i=1;i<=n;i++) 23 { 24 f[i][1]=fabs(sx[i]-sy[i]); 25 for (int j=2;j<=i, j<=k;j++) 26 for (int l=1;l<=i-1;l++) 27 { 28 if (l>=j-1) 29 { 30 double r=f[l][j-1]+fabs(sx[i]-sx[l]-sy[i]+sy[l]); 31 if (r>f[i][j]) f[i][j]=r; 32 } 33 } 34 } 35 printf("%f\n",f[n][k]); 36 return 0; 37 }