19:啤酒厂选址

总时间限制: 1000ms 内存限制: 65536kB
描述
海上有一个岛,在环海边上建有一条环岛高速公路,沿着公路有n(5 < n < 10000)个居民点,
假设每个居民点有一个编号,从0开始,按顺时针依次从小到大(即,0,1,…,n-1)编号。
在岛上啤酒很受青睐。某啤酒企业计划在岛上投资建一个啤酒厂,并根据啤酒需求每天向居住点送啤酒。
已知两个相邻的居民点的距离以及每个居住点每天的啤酒需求量(假设每个居住点每天不超过2000桶)。
假定每单位长度的路程送一桶啤酒需要的费用恒定(为单位费用)。请问,选择哪一个居民点建啤酒厂,
才能使每天送啤酒的费用最小(空车不计费用)。

输入
第一行:为居民点数目n
后面为n行,每行为一个居民点的啤酒需求量以及按顺时针离下一个居民点的距离(均为整数,空格间隔),
从编号为0的开始,按单增顺次给出。

注意:后面第n行对应于居民点(n-1)的啤酒需求量以及到编号为0的居民点距离。
输出
啤酒厂所在的居民点编号以及每天的运输费用,其间以逗号间隔
样例输入
6
500 10
300 30
350 25
400 60
700 28
200 35
样例输出
0,94100

解析:
下面以第一个村庄作为起始点(数轴零点),顺时针方向为数轴正方向
先计算每个村庄在数轴上的坐标;
利用两个村庄的坐标可以方便地计算两个村庄的顺时针距离t1;
利用环形公路周长sum和t1可以计算两个村庄逆时针距离t2;
t1和t2比较小的那一个即为两个村庄的最短距离。

依次将所有村庄当做建厂点,计算该方案的运费。
枚举完所有的方案后即可知道最小花费的方案。

本题真实的测试数据肯定没到10^4,否则本算法复杂度O(n^2)是无法通过的。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<math.h>
 4 struct obj
 5 {
 6     long long num;//该村庄啤酒需求量
 7     long long dis;//该村庄距离下一个村庄的距离(顺时针的下一个村庄)
 8     long long d;  //该村庄距离起始点的距离(相当于顺时针坐标)
 9 };
10 int main()
11 {
12     long long n,i,j;
13     struct obj *a;
14     long long sum=0;//环形公路总长
15     long long cost,minCost,minIndex;//某种建厂方案的话费;历史上各种建厂方案的最小花费
16     long long distance,t1,t2;
17 
18     freopen("data.in","r",stdin);
19     scanf("%lld",&n);
20     a=(struct obj *)malloc(sizeof(struct obj)*n);
21     for(i=0;i<n;i++)
22     {
23         scanf("%lld%lld",&a[i].num,&a[i].dis);
24         sum=sum+a[i].dis;
25     }
26 
27     a[0].d=0;//第一个村庄作为起始点
28     for(i=1;i<n;i++)
29     {
30         a[i].d=a[i-1].d+a[i-1].dis;
31     }
32 
33     minCost=0;
34     for(i=0;i<n;i++)//依次考虑选择第i个村庄做建厂点
35     {
36         cost=0;
37         for(j=0;j<n;j++)//计算从其他村庄运输到第i个村的费用
38         {
39             if(j==i) continue;
40             else
41             {
42                 t1=fabs(a[i].d-a[j].d);
43                 t2=sum-t1;
44                 distance=t1<t2?t1:t2;
45                 cost=cost+a[j].num*distance;
46             }
47         }
48         if(cost<minCost||minCost==0) { minCost=cost; minIndex=i; }
49     }
50     printf("%lld,%lld\n",minIndex,minCost);
51     return 0;
52 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值