您的位置:首页 > 其它

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

2018-03-17 21:52 357 查看
[b]题面:[/b]

传送门

[b]思路:[/b]

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)$

[b]Code:[/b]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1e9
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,a[310],sum[310];
int dp[310][310],s[310][310];
int w(int l,int r){
int t=(l+r)>>1;
return (sum[r]-sum[t])-(sum[t-1]-sum[l-1])-(r-t)*a[t]+(t-l)*a[t];
}
int main(){
int i,j,p,k,tmp;
n=read();m=read();
for(i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
for(i=0;i<=n;i++) dp[i][i]=0,s[i][i]=i;
for(p=1;p<=n-m;p++){
dp[0][p]=inf;
for(i=1;(j=i+p)<=n;i++){
dp[i][j]=inf;
for(k=s[i][j-1];k<=s[i+1][j];k++){
if((tmp=dp[i-1][k-1]+w(k,j))<dp[i][j]){
dp[i][j]=tmp;s[i][j]=k;
}
}
}
}
printf("%d\n",dp[m]
);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: