zoukankan      html  css  js  c++  java
  • 建立信号基站

    建立信号基站

      要建立一个信号基站服务n个村庄,这n个村庄用平面上的n个点表示。假设基站建立的位置在(X,Y),则它对某个村庄(x,y)的距离为max{|X – x|, |Y – y|}, 其中| |表示绝对值,我们的目标是让所有村庄到信号基站的距离和最小。 基站可以建立在任何实数坐标位置上,也可以与某村庄重合。

    输入: 给定每个村庄的位置x[],y[],x,y都是整数,满足:            -1000000000 < x,y < 1000000000 村庄个数大于1,小于101。

    输出: 所有村庄到信号基站的距离和的最小值。 关于精度: 因为输出是double。我们这样判断对错,如果标准答案是A,你的答案是a,如果|A – a| < 1e-3 我们认为是正确的,否则认为是错误的。 样例: 假设有4个村庄位置分别为 (1,4) (2,3) (0,1) (1,1) 我们的结果是5。因为我们可以选择(1.5,2.5)来建立信号基站。 bestDistance = max(|1.5-1|, |2.5-4|) + max(|1.5-2|,|2.5-3|) + max(|1.5-0|,|2.5-1|) + max(|1.5-1|,|2.5-1|) = max(0.5, 1.5) + max(0.5,0.5) + max(1.5,1.5) + max(0.5,1.5) = 1.5 + 0.5 + 1.5 + 1.5 = 5

    函数头部: C/C++ double bestDistance(int n, cons int *x, const int *y); Java class Main() {     public static double bestDistance(int [] x,int [] y); } 

    解题思路:

      解题的关键在于如何处理max{|X – x|, |Y – y|},可以通过分段函数讨论来证明,max{|x1-x2|,|y1-y2|},等价于(|x1+y1-x2-y2|+|x1-y1-(x2-y2)|)/2;

      假设信号基站的坐标是(X , Y),那么他与其他坐标的距离为max{|X – x1|, |Y – y1|} = (|X+Y-x1-y1|+|X-Y-(x1-y1)|)/2, ……,(|X+Y-xn-yn|+|X-Y-(xn-yn)|)/2;也就是最短距离

      bestDistance = 1/2  * (|X+Y-(x1+y1)| + |X-Y-(x1-y1)| + |X+Y-(x2+y2)| + |X-Y-(x2-y2)| +……+ |X+Y-(xn+yn)|+|X-Y-( xn-yn)|) -- (1-1)

      其中,x1+y1 、x1-y1  、 x2+y2 、 x2-y2 、……、xn+yn  、 xn-yn 均为常数, 通过题目所给的数组可以容易得到这些值

      假设 U(X, Y) = X + Y ,       V(X, Y) = X - Y ;可以得到

      bestDistance =  1/2  *(|U - U1| + |V - V1| + |U - U2| + |V - V2| + ……+ |U - Un| + |V - Vn|)    -- (1 - 2)

         = 1/2  *【(|U - U1| + |U - U2| + ……+ |U - Un|) + (|V - V1|  + |V - V2| + ……+ |U - Un| + |V - Vn|) 】

      这样,就转换为求函数 y = |x - x1| +  |x - x2| +  |x - x3| + ……+ |x - xn|的最小值的问题,也许有人会问,公式(1 - 2)有两个变量U , V,而函数y只有一个变量x,其实很好办,就将公式(1 - 2)按照变量 和 V分为两部分,分别求最小值,和起来也肯定是最小值;

      对于函数 y = |x - x1| +  |x - x2| +  |x - x3| + ……+ |x - xn| (x1 , x2, ……xn是从小到大排列)的最小值;可以用数学归纳法求解:

      证明:假设n = 2,则 y = |x - x1| +  |x - x2|,假设 x< x,当x ≤x< x时,y = x1 + x2 - 2x , ymin = x2- x1; 当 x1< x < x2时,

    y  = x2 - x1 ,则ymin = x2 - x1 ; 当 x ≥ x2 时,y = 2x - x1 - x2, ymin = x2 - x1;

      若 n > 2 ,

      当x < x1 < x2 <……< xn 时,y = (x1 - x) + (x2 - x) +…… +(xn - x) = (x1 + x2 + x3 +……+ xn) - n * x;

      当x1 < x < x2 <……< xn 时,y =  (x1 + x2 + x3 + …… + xn) - n * x + 2(x - x1);

      当x1 < x2 < x <……< xn 时,y =  (x1 + x2 + x3 + …… + xn) - n * x + 2[(x - x1) + (x - x2)];

      ……

      所以,当x1 < x2 < …xk < x < xk+1 <…< xn 时,

      y =  (x1 + x2 + x3 + …… + xn) - n * x + 2[(x - x1) + (x - x2) + ……+ (x - xk)]

       =  (x1 + x2 + x3 + …… + xn)  +  2[ (k - n/2)x - (x1 + x2 + ……+  xk) ]  --(1 - 4)

      对于公式(1 - 4),两边求导,可知当k - n/2 < 0 时,即k < n/2时,y 单调递增; 当k - n/2 > 0 时,即k > n/2时,y 单调递减;因为k= {1,2,3,……n},为整数,若 n 为偶数,则当 k = n/2 时,x = xky 有最小值;若 为 奇数,则当 k = (n + 1)/2时,x = xk有最小值,证毕

      综上所述,得到的最终结论是:当 n 为偶数时,y的最小值为ymin = (xk+1xk+2 + ……+xn) - (x1 + x2 +……+ xk) , k = n/2 ;当 n 为奇数时,y的最小值为ymin = (xk+1 + xk+2 + ……+xn) - (x1 + x2 +……+ xk - 1) , k = (n + 1)/2 .

      回到公式(1 - 2),分别求出(|U - U1| + |U - U2| + ……+ |U - Un|) 和 (|V - V1|  + |V - V2| + ……+ |U - Un| + |V - Vn|)的最小值,求平均数,即得到最小值bestDistance ,为程序所求.

    下面贴出我编写的代码,代码十分混乱,可读性不高,仅供参考!

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    double bestDistance(int n, const int *x, const int *y);
    double bestDistance(int n, const int *x, const int *y)
    {
        int iterx = 0, itery = 0,  temp = 0 ;
        int *tempx , *tempy;
        tempx = (int *)malloc(sizeof(int) * n);
        tempy = (int *)malloc(sizeof(int) * n);
        //time infigure
        for(iterx = 0; iterx <= n - 1; iterx++)
        {
            tempx[iterx] = x[iterx] + y[iterx];
        }
        for(iterx = 0; iterx <= n - 1; iterx++)
        {
            //tempy[iterx] = abs(x[iterx] - y[iterx]);
            tempy[iterx] = (x[iterx] - y[iterx]);
        }
    //    for(iterx = 0; iterx <= n - 1; iterx++) printf("X%d=%3d  ",iterx,tempx[iterx]);
    //    printf("\n");
        for(iterx = 0; iterx <= n - 2; iterx++)
        {
            for(itery = iterx + 1; itery <= n - 1; itery++ )
            {
                if(tempx[iterx] > tempx[itery])
                {
                    temp = tempx[iterx];
                    tempx[iterx] = tempx[itery];
                    tempx[itery] = temp;
                }
            }
        }
    //    for(iterx = 0; iterx <= n - 1; iterx++) printf("X%d=%3d  ",iterx,tempx[iterx]);
    //    printf("\n");
        for(iterx = 0; iterx <= n - 2; iterx++)
        {
            for(itery = iterx + 1; itery <= n - 1; itery++ )
            {
                if(tempy[iterx] > tempy[itery])
                {
                    temp = tempy[iterx];
                    tempy[iterx] = tempy[itery];
                    tempy[itery] = temp;
                }
            }
        }
        //for(iterx = 0; iterx <= n - 1; iterx++) printf("X%d=%3d  ",iterx,tempy[iterx]);
    
        long long  sumXM = 0, sumXL = 0 , sumYM = 0 , sumYL = 0;
        int tempN = 0;
        // SUM_Xn - sumXn/2
        for(iterx = 0; iterx <= n / 2 - 1; iterx++)
        {
            sumXL = sumXL + tempx[iterx];
        }
        for(iterx = 0; iterx <= n / 2 - 1; iterx++)
        {
            sumYL = sumYL + tempy[iterx];
        }
        // SUM_Yn - sumYn/2
        if(n % 2 == 0)
        {
            tempN = n / 2 ;
        }
        else
        {
            tempN = n / 2 + 1;
        }
        for(iterx = tempN; iterx <= n - 1; iterx++)
        {
            sumXM = sumXM + tempx[iterx];
        }
    
        for(iterx = tempN; iterx <= n - 1; iterx++)
        {
            sumYM = sumYM + tempy[iterx];
        }
    //    printf("\n(sumXM - sumXL)/2 = %lf\n",(sumXM - sumXL) / 1.0);
    //    printf("\n(sumYM - sumYL)/2 = %f\n",(sumYL) / 1.0);
        return (sumXM - sumXL + sumYM - sumYL) / 2.0;
    }
    int main(void)
    {
        //time_t before = time(NULL);
        //printf("before = %ld秒\n", before);
        int x[19] = {858442934,-161749718,-55910439,347569202,-660170269,-982075453,-860790164,947179323,312298821,-285196111,967545126,-777105315,-630974471,-713895350,745616673,840630174,-597730146,-205693089,24677872};
        int y[19] = {449535070,160026431,705809990,121634879,648304545,-392329548,-447666131,-829918127,926665890,943182185,601133076,-848803337,89719473,-586785144,832132969,-111884761,-556530757,65860874,978639057};
        int n = 19;
        printf("\nthe result is %lf",bestDistance(n , x , y));
        //time_t after = time(NULL);
        //printf("after = %ld秒\n", after);
    
        //printf("总共执行时间为:%ld秒\n", after - before);
        return 0;
    }

    测试用例有:

    int n = 19;

    int x[19] = {858442934,-161749718,-55910439,347569202,-660170269,-982075453,-860790164,947179323,312298821,-285196111,967545126,-777105315,-630974471,-713895350,745616673,840630174,-597730146,-205693089,24677872};
    int y[19] = {449535070,160026431,705809990,121634879,648304545,-392329548,-447666131,-829918127,926665890,943182185,601133076,-848803337,89719473,-586785144,832132969,-111884761,-556530757,65860874,978639057};

    结果是 13560445376.500000

  • 相关阅读:
    C#注意事项
    组件化开发
    kettle导数删除并插入更新数据_20161130
    MySQL_各城市在线产品天订单数据20161130
    MySQL_杭州11月1-29号在线产品在线天数、销售天数_20161129
    kettle每天自动发送邮件总结_20161128
    MYSQL_与excel结合在excel中用&连接符快速创建表头_20161125
    MySQL_杭州拱墅区、西湖区近9-11月销售过的产品_20161125
    MySQL_产品昨日库存与历史入库历史出库成本_20161124
    MySQL11月16-11月21日活动赠送的优惠券使用率_20161124
  • 原文地址:https://www.cnblogs.com/bestDavid/p/stationInfo.html
Copyright © 2011-2022 走看看