题解 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] << '
';
    return 0;    
}
原文地址:https://www.cnblogs.com/colazcy/p/11622090.html