原题链接:山区建小学 - 洛谷
思路:
参考:题解 P4677 【山区建小学】 - hsfzLZH1 的博客 - 洛谷博客
注意:
1) 细节方面格外要注意,初始化要注意,这个题如果 dp[i][0]当i不为0的时候会有问题,因为不会存在前面i个村庄都没有学校(相当于前面距离和为0)然后后面的村庄有学校的情况;
2) 而且题目给的是n - 1个距离,可以先设a[1] = 0,然后依次得到a[i]的坐标(相当于坐标)
AC代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define PII pair<int,int>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for(int i = n; i >= 1; ++i)
using namespace std;
const double pi = acos(-1.0);
const int N = 510;
ll a[N], s[N], f[N][N], dp[N][N];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
a[1] = 0;
for(int i = 2; i <= n; i++) scanf("%lld", &a[i]), a[i] += a[i - 1];
rep(i, n) s[i] = s[i - 1] + a[i];
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
{
int mid = (i + j) >> 1;
f[i][j] = (mid - i) * a[mid] + s[i - 1] - s[mid - 1] + s[j] - s[mid] - (j - mid) * a[mid];
}
memset(dp, 0x3f, sizeof dp);
dp[0][0] = 0;
rep(i, n)
for(int j = 1; j <= min(m, i); j++)
for(int k = j - 1; k < i; k++) dp[i][j] = min(dp[i][j], dp[k][j - 1] + f[k + 1][i]); //k从0开始,因为dp[0][0]要用上 k从j - 1开始就可以了, 这样会快很多
printf("%lld", dp[n][m]);
return 0;
}