题解 P4767 [IOI2000]邮局
Posted colazcy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P4767 [IOI2000]邮局相关的知识,希望对你有一定的参考价值。
Solution [IOI2000]邮局
题目大意:在\(n\)个村庄中选\(m\)个邮局,求最小代价和
分析:
首先我们假设只有一个邮局,利用初中数学可知邮局放中间是最优秀的
设\(w[l][r]\)为\([l,r]\)内放一个邮局的最小代价和
设\(f[i][j]\)为\([1,i]\)内放\(j\)个邮局的最小代价和
显然\(f[i][j] = min\f[k][j - 1] + w[k + 1][i] \quad k \in [1,i - 1]\\)
然后这玩意儿如果\(O(n)\)转移那么复杂度\(O(n^3)\)直接上天,打表等思路证明一下\(w\)满足四边形不等式,所以有决策单调性
设\(m[i][j]\)为\(f[i][j]\)的最优决策点
有\(m[i][j - 1] \leq m[i][j] \leq m[i + 1][j]\)
注意邮局坐标要排序
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 3333;
int val[maxn],sum[maxn],w[maxn][maxn],f[maxn][maxn],m[maxn][maxn],n,v;
inline int query(int a,int b)return a <= b ? sum[b] - sum[a - 1] : 0;
int main()
ios::sync_with_stdio(false);
cin >> n >> v;
for(int i = 1;i <= n;i++)cin >> val[i];
sort(val + 1,val + 1 + n);
for(int i = 1;i <= n;i++)sum[i] = sum[i - 1] + val[i];
for(int l = 1;l <= n;l++)
for(int r = l;r <= n;r++)
int mid = (l + r) >> 1;
w[l][r] += val[mid] * (mid - l) - query(l,mid - 1);
w[l][r] += query(mid + 1,r) - val[mid] * (r - mid);
memset(f,0x3f,sizeof(f));
for(int i = 1;i <= n;i++)f[i][1] = w[1][i];
for(int j = 2;j <= v;j++)
m[n + 1][j] = n;
for(int i = n;i >= 1;i--)
for(int k = m[i][j - 1];k <= m[i + 1][j];k++)
if(f[k][j - 1] + w[k + 1][i] < f[i][j])
f[i][j] = f[k][j - 1] + w[k + 1][i],m[i][j] = k;
cout << f[n][v] << '\n';
return 0;
以上是关于题解 P4767 [IOI2000]邮局的主要内容,如果未能解决你的问题,请参考以下文章