洛谷P4767 [IOI2000]邮局

题目链接:P4767 [IOI2000]邮局
题目大意:
整数轴上有 \(V\) 个村庄,要在其中一些村庄中建 \(P\) 个邮局,求每个村庄和最近的邮局之间所有距离的总和的最小值。
\(1\leq P\leq 300, P\leq V\leq 3000\)

思路:
\(val(i,j)\) 为在 \([j,i]\) 区间上建一个邮局后该区间距离和的最小值,设 \(dp[i][j]\) 为在 \([1,j]\) 上建了 \(i\) 个邮局时的答案,有朴素 \(O(V^2P)\) 转移:

\[dp[i][j]=\min_{0\leq k<j}\{dp[i-1][k]+val(j,k+1)\} \]

计算 \(val(i,j)\) :,记 \(s[i]\) 为前 \(i\) 个村庄坐标和,即 \(s[i]=\sum_{j=1}^i{a[j]}\) ,根据中位数的性质,显然邮局建在中位数处是最优的,所以记 \(mid=(i+j)/2\) ,有:

\[val(i,j)=s[i]-s[mid]-(i-mid)*a[mid]-(s[mid-1]-s[j-1]-(mid-j)*s[mid])\\=s[i]+s[j-1]-2*s[mid]-(2*mid-i-j-1)*a[mid] \]

考虑将转移优化,\(val(i,j)\) 具有满足四边形不等式的潜质,对于 \(val(i,j+1)\)\(val(i+1,j)\) ,两者邮局建立的位置相同,设为 \(mid\) ,可以得到:

\[val(i,j+1)+val(i+1,j)=2*val(i,j+1)-(a[i+1]-a[mid])-(a[mid]-a[j]) \]

\[\quad\because val(i,j)\leq val(i,j+1)+(a[mid]-a[j]),\quad val(i+1,j+1)\leq val(i,j+1)+(a[i]-a[mid]) \]

两式相加可得:

\[val(i,j+1)+val(i+1,j)\geq val(i,j)+val(i+1,j+1) \]

又因为显然 \(val(i+1,j)\geq val(i,j+1)\) ,所以 \(dp[i][j]\) 满足二维决策单调性,即 \(p[i][j-1]\leq p[i,j]\leq p[i+1][j]\) ,其中 \(p[i][j]\)\(dp[i][j]\) 的决策点 \(k\) ,这样我们就将时间复杂度降到了 \(O(\sum_{i=1}^P\sum_{j=1}^V(p[i+1][j]-p[i][j-1]))=O(\sum_{i=1}^P(p[i+1][V]-p[1][V-i]+V-i))=O(VP)\) ,可以轻松通过此题。

实现细节:

  • 由于转移 \(dp[i][j]\) 时要用到 \(dp[i][j-1]\)\(dp[i+1][j]\) 的决策,要采用区间DP的顺序进行循环。
  • 初值:\(dp[i][i]=0\)\(p[i][i]=i\)

Code:

#include<iostream>
#include<cstring>
#define N 3020
using namespace std;
int a[N],p[N][N],dp[N][N],s[N];
int n,m;
int val(int i,int j){
    int mid=(i+j)>>1;
    return s[i]-s[mid]+(2*mid-i-j)*a[mid]-s[mid-1]+s[j-1];
}
bool Min(int &a,int b){
    if(a<=b)return false;
    a=b;return true;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i],s[i]=s[i-1]+a[i];
    memset(dp,0x3f,sizeof(dp));
    for(int i=0;i<=n;i++)dp[i][i]=0,p[i][i]=i;
    for(int len=1;len<=n-m;len++){
        for(int i=1,j=1+len;j<=n;i++,j++){
            for(int k=p[i][j-1];k<=p[i+1][j];k++)
                if(Min(dp[i][j],dp[i-1][k-1]+val(j,k)))p[i][j]=k;
        }
    }
    cout<<dp[m][n];
    return 0;
}
posted @ 2020-12-02 15:21  Neal_lee  阅读(168)  评论(1编辑  收藏  举报