luogu_P4767 [IOI2000]邮局

Posted papercloud

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu_P4767 [IOI2000]邮局相关的知识,希望对你有一定的参考价值。

传送门

Description

高速公路旁边有一些村庄。高速公路表示为整数轴,每个村庄的位置用单个整数坐标标识。没有两个在同样地方的村庄。两个位置之间的距离是其整数坐标差的绝对值。

邮局将建在一些,但不一定是所有的村庄中。为了建立邮局,应选择他们建造的位置,使每个村庄与其最近的邮局之间的距离总和最小。

你要编写一个程序,已知村庄的位置和邮局的数量,计算每个村庄和最近的邮局之间所有距离的最小可能的总和。

Solution

大概是把dp的常见优化的经典练习题都打了一波。

这是四边形不等式优化的题目。证明?百度百科上就很不错了,就不说了。

满足(f[i][j]) 的决策点会在(f[i][j-1])(f[i+1][j])的决策点之间


Code

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define MN 3005
#define mN 305
int V,P,a[MN],f[MN][mN],q[MN],d[MN][MN],g[MN][mN];
inline int dis(int l,int r)
{
    if(d[l][r]) return d[l][r];
    else return d[l][r]=q[r]+q[l-1]-q[(l+r)>>1]-q[(l+r-1)>>1];
}
int main()
{
    V=read();P=read();
    memset(f,0x3f,sizeof f);
    register int i,j,k;
    for(i=1;i<=V;++i) a[i]=read(),q[i]=q[i-1]+a[i];
    std::sort(a+1,a+V+1);

    for(i=1;i<=V;++i) f[i][1]=dis(1,i);

    for(g[V+1][k=2]=V;k<=P;++k,g[V+1][k]=V)
        for(i=V;i>=1;--i)for(j=g[i][k-1];j<=g[i+1][k];++j)
            if(f[j][k-1]+dis(j+1,i)<f[i][k])
                f[i][k]=f[j][k-1]+dis(j+1,i),g[i][k]=j;
    return 0*printf("%d
",f[V][P]);
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

以上是关于luogu_P4767 [IOI2000]邮局的主要内容,如果未能解决你的问题,请参考以下文章

[IOI2000]邮局

[IOI2000] 邮局

四边形不等式POJ1160[IOI2000]-Post Office

IOI 2000 Walls Floyd+枚举

IOI2000 Post Office (POJ1160)

Laoj P1285 回文词(ioi2000)