BSOJ: 2699 【ZJOI2010】基站选址
来源:互联网 发布:淘宝闪电退款 编辑:程序博客网 时间:2024/05/16 07:01
Description
有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di。需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci。如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就称它被覆盖了。如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi。现在的问题是,选择基站的位置,使得总费用最小。
Input
输入文件的第一行包含两个整数N,K,含义如上所述。
第二行包含N-1个整数,分别表示D2,D3,…,DN ,这N-1个数是递增的。
第三行包含N个整数,表示C1,C2,…CN。
第四行包含N个整数,表示S1,S2,…,SN。
第五行包含N个整数,表示W1,W2,…,WN。
Output
输出文件中仅包含一个整数,表示最小的总费用。
Sample Input
3 2
1 2
2 3 2
1 1 0
10 20 30
Sample Output
4
Hint
40%的数据中,N<=500;
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。
这道题的动规模型很明显:
我们可以写出如下DP方程:
最初的位置信息可以采用二分来处理。
现在我们对DP进行优化,这里采用线段树比较好。
对每一个
当计算了
代码如下:
#include<iostream>#include<iomanip>#include<cstring>#include<cmath>#include<cstdio>#include<vector>using namespace std;int n,k;int D[20005],C[20005],S[20005],W[20005];int st[20005],ed[20005];int F[20005];vector<int>P[20005];struct tree{ int l,r,Min,add;}Tree[20005*4];void pushup(int root){ Tree[root].Min=min(Tree[root*2].Min,Tree[root*2+1].Min);}void pushdown(int root){ if(Tree[root].add){ int t=Tree[root].add; Tree[root].add=0; Tree[root*2].add+=t; Tree[root*2].Min+=t; Tree[root*2+1].add+=t; Tree[root*2+1].Min+=t; }}void build(int root,int l,int r){ Tree[root].add=0; Tree[root].Min=0x7fffffff; Tree[root].l=l; Tree[root].r=r; if(l==r){ Tree[root].Min=F[l]; return ; } build(root*2,l,(l+r)>>1); build(root*2+1,((l+r)>>1)+1,r); pushup(root);}int query(int root,int l,int r){ if(l>r)return 0; if(Tree[root].l>=l&&Tree[root].r<=r){ return Tree[root].Min; } else{ pushdown(root); int mid=(Tree[root].l+Tree[root].r)>>1; int Ans=0x7fffffff; if(l<=mid)Ans=min(Ans,query(root*2,l,r)); if(r>mid)Ans=min(Ans,query(root*2+1,l,r)); return Ans; }}void Add(int root,int l,int r,int x){ if(l>r)return ; if(Tree[root].l>=l&&Tree[root].r<=r){ Tree[root].add+=x; Tree[root].Min+=x; } else { pushdown(root); int mid=(Tree[root].l+Tree[root].r)>>1; if(l<=mid)Add(root*2,l,r,x); if(r>mid)Add(root*2+1,l,r,x); pushup(root); }}int DP(){ int temp=0; for(int i=1;i<=n;i++){ F[i]=temp+C[i]; for(int j=0;j<P[i].size();j++){ temp+=W[P[i][j]]; } } int ans=F[n]; for(int j=2;j<=k;j++){ build(1,1,n); for(int i=1;i<=n;i++){ F[i]=query(1,1,i-1)+C[i]; for(int j=0;j<P[i].size();j++){ Add(1,1,st[P[i][j]]-1,W[P[i][j]]); } } ans=min(ans,F[n]); } return ans;}int main(){ scanf("%d%d",&n,&k); for(int i=2;i<=n;i++){scanf("%d",&D[i]);} for(int i=1;i<=n;i++){scanf("%d",&C[i]);} for(int i=1;i<=n;i++){scanf("%d",&S[i]);} for(int i=1;i<=n;i++){scanf("%d",&W[i]);} n++; k++; D[n]=0x7fffffff/2; for(int i=1;i<=n;i++){ int l=D[i]-S[i]; int r=D[i]+S[i]; st[i]=lower_bound(D+1,D+n+1,l)-D; ed[i]=lower_bound(D+1,D+n+1,r)-D; if(D[i]+S[i]<D[ed[i]])ed[i]--; P[ed[i]].push_back(i); } printf("%d",DP()); return 0;}
0 0
- BSOJ: 2699 【ZJOI2010】基站选址
- 1835: [ZJOI2010]base 基站选址
- BZOJ1835 [ZJOI2010]base 基站选址
- [BZOJ1835][ZJOI2010]base 基站选址
- BZOJ1835 [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- 【bzoj1835】【ZJOI2010】【基站选址】【dp+线段树】
- bzoj 1835: [ZJOI2010]base 基站选址
- [BZOJ]1835: [ZJOI2010]base 基站选址 线段树+DP
- bzoj1835 [ZJOI2010]base 基站选址(dp+线段树优化)
- bzoj 1835: [ZJOI2010]base 基站选址 线段树优化dp
- 基站选址
- 基站选址
- bzoj 1835: [ZJOI2010]base 基站选址(线段树优化dp)
- BSOJ: 2697 -- 【ZJOI2010】数字计数
- bsoj 2684 【CEOI2004】锯木厂选址
- 【hihoCoder】基站选址
- MATLAB-遗传算法
- 智能指针与数组
- 手机开发实战78——URL简介
- 高德地图:按F12都查不到切片坐标,想了个办法自己测试出结果,谷歌切片也是这样排列的吗?
- Uri Demo
- BSOJ: 2699 【ZJOI2010】基站选址
- 手机开发实战79——Javascript介绍1
- java连接Sql Server2008 方法二
- 如何简单形象又有趣地讲解神经网络是什么?
- 51nod--多重背包
- 【转】纯CSS3制作的Tab选项卡
- 手机开发实战80——Javascript介绍2
- Android蓝牙篇:(一)基础篇
- UNIX 环境高级编程(九)—— fork 函数与 I/O 函数