问题描述
规则如下:
每个小区只能由同一侧连续的若干座单元楼组成。且两侧都恰有 K 个小区(每个小区至少有一栋楼)。
两侧的小区划分规则应该相同,比如,若左边的房子被分成 {1,2},{3} 这两个小区,那么右边也应该如此。
这样两边合计一共有 K 对小区。
用 ai,bii,bi 表示左右两边每座楼的人口在同侧所有单元楼总人口中所占的百分比,定义一个小区的相对拥挤程度为其人口百分比之和(左边就是对应 aia_iai 的和,右边是对应 bib_ibi 的和)。定义这条街道的总拥挤程度为左右两边 KKK 对小区的相对拥挤程度之差的绝对值之和。
现在,请你求出可能的最大拥挤程度。
输入格式
第二行 N 个实数,第 i 个数为 aii。
第三行 N 个实数,第 i 个数位 bii。
输出格式
一个实数,表示这条街道的最大相对拥挤程度,保留到小数点后六位。
样例输入
3 20.1 0.75 0.15
0.4 0.3 0.3
样例输出
0.600000
题解:
本题是一道典型的动态规划。
用f[i,j]表示两边的前I座楼中,被分为J段的情况下,最大可能的拥挤程度之差。
转移方程为f[i,j]=MAX {F[l,j-1]+|Px({l+1,...,i})-Py({l+1,...i})|}
其中Px和Py分别表示将两边大楼划分出(L,I]这段作为小区的拥挤程度之和。
再注意一下边界条件即可。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define maxn 1000
#define maxm 100
using namespace std;
double a[maxn],b[maxn],dp[maxn][maxm];
int n,k;
double gf_abs(double x)
{
return x>0?x:-1.0*x;
}
void get_ans()
{
for(int i=1;i<=n;i++)
{
dp[i][1]=gf_abs(a[i]-b[i]);
for(int loop=2;loop<=i&&loop<=k;loop++)
{
for(int j=loop-1;j<i;j++)
{
dp[i][loop]=max(dp[i][loop],dp[j][loop-1]+gf_abs(a[i]-a[j]-b[i]+b[j]));
}
}
}
}
void init()
{
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];
}
}
void solve()
{
scanf("%d %d",&n,&k);
init();
get_ans();
printf("%.6lf",dp[n][k]);
}
int main()
{
solve();
return 0;
}