题解:P2803 学校选址 II
题目传送门
思路
可以发现,这一题
可以发现这题中只有
定义
那么怎么求
那么为了使得距离和最小,所以
找到这个
有了
代码
#include<bits/stdc++.h>
using namespace std;
int a[120],b[120];
int s1[120][120],s2[120][120];//s1[i][j]表示i到j的学生人数,s2[i][j]表示i到j的距离
long long f[120][120];\\f[i][j]表示在i到j之间安置一所学校学生所走的距离和的最小值
long long dp[120][120];\\dp[i][j]表示对前j栋楼来说,建造i所学校学生所走的距离和的最小值
int main()
{
int n,m;
cin>>n>>m;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=2;i<=n;i++) cin>>b[i];
for (int i=1;i<=n;i++)//计算学生人数区间
{
for (int j=i;j<=n;j++)
{
s1[i][j]=s1[i][j-1]+a[j];
}
}
for (int i=1;i<=n;i++)//计算距离
{
for (int j=i+1;j<=n;j++)
{
s2[i][j]=s2[i][j-1]+b[j];
}
}
memset(dp,0x3f,sizeof(dp));//赋极大值(用于找极小值)
memset(f,0,sizeof(f));//清空
for (int i=1;i<=n;i++)
{
for (int j=i;j<=n;j++)
{
for (int l=i;l<=j;l++)
{
if (s1[i][l]<s1[l+1][j]) continue;//找两边学生人数差最小的中点
for (int k=i;k<=l;k++) f[i][j]+=a[k]*s2[k][l];
for (int k=l+1;k<=j;k++) f[i][j]+=a[k]*s2[l][k];
//计算最短距离
break;
}
}
}
for (int i=1;i<=n;i++) dp[1][i]=f[1][i];//初始化
for (int i=2;i<=m;i++)
{
for (int j=i;j<=n;j++)
{
for (int l=i-1;l<=j-1;l++)
{
dp[i][j]=min(dp[i][j],dp[i-1][l]+f[l+1][j]);//状态转移方程
}
}
}
cout<<dp[m][n];//输出
}