[LUOGU] P4767 [IOI2000]邮局
2024-09-07 18:55:26
https://www.luogu.org/problemnew/show/P4767
四边形不等式好题!
可以设f[i][j]表示前i个村庄,建了j个邮局的最小代价。
转移:f[i][j]=min{f[k][j-1]+dis[k+1][i]}
也就是枚举断点,断点后整个区间建造一个邮局并强制整个区间都选择它。
这个邮局在哪里最优呢?由人类智慧知,在中位数处最优。
注意到这样的转移下,时间复杂度是O(m*n^2)的,不行
这是一个前缀问题,但是同时它也是一个区间问题,回忆四边形不等式的形式,尝试套上去
至此,我们就有了O(nm)的优秀做法。
(证明暂时不会,有会证明的欢迎留言..)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio> using namespace std; inline int rd(){
int ret=,f=;char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-:;
while(isdigit(c))ret=ret*+c-'',c=getchar();
return ret*f;
} const int MAXN=; int n,m;
int val[MAXN],sum[MAXN],dis[MAXN][MAXN];
int f[MAXN][],tran[MAXN][]; int main(){
memset(f,0x3f,sizeof(f));
n=rd();m=rd();
for(int i=;i<=n;i++) val[i]=rd();
sort(val+,val++n);
for(int i=;i<=n;i++) sum[i]=sum[i-]+val[i];
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
dis[i][j]=dis[i][j-]+val[j]-val[i+j>>];
for(int i=;i<=n;i++) f[i][]=dis[][i];
int mn=<<,mnid;
for(int j=;j<=m;j++){
tran[n+][j]=n-;
for(int i=n;i>=j;i--){
for(int k=tran[i][j-];k<=tran[i+][j];k++){
if(f[k][j-]+dis[k+][i]<f[i][j]){
f[i][j]=f[k][j-]+dis[k+][i];
tran[i][j]=k;
}
}
}
}
cout<<f[n][m];
return ;
}
最新文章
- Unity5 AssetBundle
- bootstrap-select去除蓝色边框outline
- IntelliJ 有的时候移动滚动条后会自动回到光标所在位置的解决方法
- Android_layout 布局(一)
- Round Numbers(组合数学)
- Practice: Process logs with Apache Hadoop
- Android中Chronometer 计时器和震动服务控件
- ajax实现跨域访问的两种方式
- RMQ(ST表)
- js常用正则表达式判断
- javeEE第一周
- jq 通配符,模糊查询
- 新学python画一个爱心
- 【Python】【IO】
- Visio View:打开VSd时,IE弹出已停止工作。
- 测试oracle数据库连接
- [Usaco2007 Jan]Balanced Lineup
- JavaScript 移动和触摸框架
- 先进驾驶员辅助系统ADSA
- 在Linode VPS上搭建最新版Transmission