[POJ1160] Post Office [四边形不等式dp]

题面:

传送门

思路:

dp方程实际上很好想

设$dp\left[i\right]\left[j\right]$表示前$j$个镇子设立$i$个邮局的最小花费

然后状态转移:

$dp\left[i\right]\left[j\right]=min\left(dp\left[i-1\right]\left[k-1\right]+w\left(k,j\right)\right)$

其中$w$表示在这个闭区间内设立一个邮局的最小费用

推一下发现这里$w$可以$O\left(1\right)$前缀和计算,或者$O\left(n^2\right)$预处理

本来到这里这道题目其实就解决了(因为$n$只有$300$)

但是我们本着优化到底的精神,来重新审视这个方程,结果发现:

这不就是四边形不等式第二类情形吗!

然后证明一下$w$的四边形不等式,然后优化,变成$O\left(n^2\right)$

 

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define inf 1e9
 6 using namespace std;
 7 inline int read(){
 8     int re=0,flag=1;char ch=getchar();
 9     while(ch>'9'||ch<'0'){
10         if(ch=='-') flag=-1;
11         ch=getchar();
12     }
13     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
14     return re*flag;
15 }
16 int n,m,a[310],sum[310];
17 int dp[310][310],s[310][310];
18 int w(int l,int r){
19     int t=(l+r)>>1;
20     return (sum[r]-sum[t])-(sum[t-1]-sum[l-1])-(r-t)*a[t]+(t-l)*a[t];
21 }
22 int main(){
23     int i,j,p,k,tmp;
24     n=read();m=read();
25     for(i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
26     for(i=0;i<=n;i++) dp[i][i]=0,s[i][i]=i;
27     for(p=1;p<=n-m;p++){
28         dp[0][p]=inf;
29         for(i=1;(j=i+p)<=n;i++){
30             dp[i][j]=inf;
31             for(k=s[i][j-1];k<=s[i+1][j];k++){
32                 if((tmp=dp[i-1][k-1]+w(k,j))<dp[i][j]){
33                     dp[i][j]=tmp;s[i][j]=k;
34                 }
35             }
36         }
37     }
38     printf("%d\n",dp[m][n]);
39 }

 

posted @ 2018-03-17 21:52  dedicatus545  阅读(444)  评论(0编辑  收藏  举报