基站选址

问题描述

描述
需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上。

网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方。

网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离)。

在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价。

输入
第一行为一个整数T,表示数据组数。

每组数据第一行为四个整数:N, M, A, B。

接下来的A+B行每行两个整数x, y,代表一个座标,前A行表示各用户的座标,后B行表示各通讯公司的座标。

输出
对于每组数据输出一行”Case #X: Y”,X代表数据编号(从1开始),Y代表所求最小代价。

数据范围
1 ≤ T ≤ 20

1 ≤ x ≤ N

1 ≤ y ≤ M

1 ≤ B ≤ 100

小数据

1 ≤ N, M ≤ 100

1 ≤ A ≤ 100

大数据

1 ≤ N, M ≤ 107

1 ≤ A ≤ 1000

样例输入
2
3 3 4 1
1 2
2 1
2 3
3 2
2 2
4 4 4 2
1 2
2 4
3 1
4 3
1 4
1 3
样例输出
Case #1: 4
Case #2: 13

思考:只需考虑一个曼哈顿距离,则可对B输入循环

设(x,y)为最佳位置,xb,yb 为最佳的通讯公司位置,则有:
costx=ixi2+ax2+2ixix+|xxb|
costy=iyi2+ay2+2iyiy+|yyb|
cost=costx+costy

从中可以看出,costx 取最小值时, x=ixia±12acosty 同理

代码

import java.util.Scanner;
/**
 * Created by Risky on 2015/4/19.
 */
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        for(int k = 1; k <= n; k++){
            long N = in.nextLong();
            long M = in.nextLong();
            int a = in.nextInt();
            int b = in.nextInt();
            long euDisX = 0, euDisY = 0, manDisX = 0, manDisY = 0;
            for(int i = 0; i < a; i++){
                long xa = in.nextLong();
                long ya = in.nextLong();
                euDisX += xa * xa;    euDisY += ya * ya;
                manDisX += xa;         manDisY += ya;
            }
            long cost = Long.MAX_VALUE;
            for(int j = 0; j < b; j++){
                long temp = Long.MAX_VALUE;
                //long total = 0;
                long xb = in.nextLong();
                long yb = in.nextLong();

                for(long x = manDisX / a - 1; x < manDisX / a + 2; x++){
                    long cx = a * x *x  + euDisX - 2 * manDisX * x  + Math.abs(x - xb);
                    if(cx < temp)
                        temp = cx;
                }
                long total = temp;
                temp = Long.MAX_VALUE;

                for(long y = manDisY / a - 1; y < manDisY / a + 2; y++){
                    long cy = a * y*y  + euDisY - 2 * manDisY * y  + Math.abs(y - yb);
                    if(cy < temp)
                        temp = cy;
                }
                total += temp;
                if(total < cost)
                    cost = total;
            }
            System.out.println("Case #" + k +": "+ cost);

        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章