酒厂选址
来源:互联网 发布:asp.net mvc 获取域名 编辑:程序博客网 时间:2024/05/01 00:20
【问题描述】
某岛的居民酷爱一种无酒精啤酒。以前这种啤酒都是从波兰进口,但今年居民们想建一个自己的啤酒厂。岛上所有城市都坐落在海边,并且由一条沿海岸线的环岛高速路连接。酒厂的投资者收集了关于啤酒需求量的信息,即每天各城市消费的啤酒桶数。另外还知道每相邻城市之间的距离(单位:千米),另外还知道每桶啤酒每千米的运费是1元。日运费是将所需的啤酒运到所有城市所需费用之和。日运费的多少和啤酒厂的选址有关系。投资者想找到一个合适的城市来修建酒厂。以使日运费最少。
任务:请设计一个程序,读入城市的数目、相邻两城市间的距离以及每个城市消费啤酒的桶数,计算和输出最小的日运费。
【输入格式】
第1行:一个整数N,表示城市数量。城市沿环岛高速编号,所以相邻两城市的编号也是相邻的(城市1和城市N被认为是相邻的)。
以下N行,每行两个非负整数。第i+1行的数Zi和Di分别是第i个城市每天消费啤酒桶数和到下一个城市的距离(千米)。环岛高速的总长不超过1000000千米。每座城市的日消费量不超过1000桶。
【输出格式】
一个整数,表示日运费的最小值。
【输入样例】
5
1 2
3 2
2 6
1 3
2 2
【输入样例解释】
样例给出的图形如下,其中黑色数字表示城市编号,括号里的蓝色数字表示该城市的消费,红色数字表示相邻城市之间的距离。
【输出样例】
21
【输出样例解释】
酒店可建设在城市1、城市2、城市3、城市4、城市5的日运送费用计算如下表:
所以,酒厂建在城市2时,日运送费用最少,为21。
【数据范围】
对于50%的数据有:5<=N<=5000
对于100%的数据有:5<=N<=100000,环岛高速的总长不超过1000000千米。每座城市的日消费量不超过1000桶。
很容易看出这是一道中位数的题,我们也容易想到要破环,但重点就在于不能超时(所以不能用暴力)。我们会发现每次破环后,中位数是只往后退,不会前进的(毕竟前面的少了,后面的多了),所以我们可以直接看它需要往后退多少。
然后就需要一下计算了,详见代码注释:
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cmath>using namespace std;const int maxn=200005;const int inf=1000000000;int a[maxn],n,d[maxn],totd=0,tota=0,g[maxn];int read(){ int x=0,ok=0; char ch; ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); while((ch>='0'&&ch<='9')||ch=='-') { if(ch=='-') ok=1; else x=x*10+ch-'0'; ch=getchar(); } return ok==1?-x:x;}void init(){ n=read(); d[1]=0; g[0]=0; for(int i=1;i<=n;i++) { a[i]=read(); g[i]=g[i-1]+a[i];//酒的前缀和。 tota+=a[i]; d[i+1]=read()+d[i];//距离(1为起点)。 } totd=d[n+1]; for(int i=1;i<=n;i++) { a[i+n]=a[i]; d[n+i]=d[i]+totd; g[i+n]=g[i+n-1]+a[i]; }}int main(){ //freopen("winery.in","r",stdin); //freopen("winery.out","w",stdout); init(); long long ans=100000000000000ll,q=0; int t=1;//先假设中位数是1. for(int i=1;i<=n;i++) { int k=0; while(g[t+k]-g[i-1]<tota-(g[t+k]-g[i-1])) k++;//看要退几个. if(i==1) { for(int j=1;j<=n;j++) q+=a[j]*abs(d[k+t]-d[j]);//第一次需要暴力算花费。 } if(i>1) { q-=(d[t]-d[i-1])*a[i-1];//减去这次去掉的点的花费。 q-=(tota-(g[t+k-1]-g[i-2]))*(d[t+k]-d[t]);//中位数以后的点比之前要少的花费(不算多加的点)。 for(int p=1;p<k;p++)//2次中位数直接的点的花费(重新算)。 { q-=a[t+p]*(d[t+p]-d[t]); q+=a[t+p]*(d[t+k]-d[t+p]); } q+=(d[t+k]-d[t])*(g[t]-g[i-1]);//上一个中位数之前的点多的花费(不算去掉的点)。 q+=(d[i-1+n]-d[t+k])*a[i-1];//多的那个点的花费. } ans=min(ans,q); t=t+k; } cout<<ans; return 0;}
- 酒厂选址
- 酒厂选址
- codevs 1507酒厂选址
- Codevs 1507 酒厂选址
- [codevs1507] 酒厂选址
- Codevs 1507 酒厂选址
- [codevs1507]酒厂选址
- codevs 1507 酒厂选址 题解报告
- 选址
- 便利店选址
- 仓库选址
- 基站选址
- 基站选址
- 发射器选址
- 为新建医院选址
- 学校超市选址问题
- 关于店铺选址1
- 网站公司选址
- Linux夜间模式(f.lux)
- Hive On Spark执行计划总结
- BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
- 使用链表管理内存
- CSS样式表中#和.和缺省的区别
- 酒厂选址
- ubuntu下安装搜狗输入法
- 简单扼要的socket
- 腾讯内部简历评定标准,有兴趣的同学参考。
- 调用fwrite函数向一个文件写入十六进制数据时,当写入值为0x0A时,其前面总是加上一个0x0D
- ubuntu安装tomcat
- 阿里2015春季实习校招笔试题-自己尝试做的答案
- Mysql的基本操作命令 (转载)
- iis日志运营报告