蓝桥杯真题:C村建k个邮局

标题:邮局
C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。
现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。

【输入格式】
输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。
接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。
接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。
在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。

【输出格式】
输出一行,包含k个整数,从小到大依次表示你选择的备选邮局编号。(备选邮局按输入顺序由1到m编号)

【样例输入】
5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2

【样例输出】
2 4

【数据规模和约定】
对于30%的数据,1<=n<=10,1<=m<=10,1<=k<=5;
对于60%的数据,1<=m<=20;
对于100%的数据,1<=n<=50,1<=m<=25,1<=k<=10。

【资源约定】
 峰值内存消耗 < 64M

CPU消耗  < 3000ms

-------------------------------------------

思路:用死办法,遍历每种结果取最小值。


import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import static java.lang.Math.*;
public class BlueBridgeExcercise5{
    private static int[] combiArr; //临时数组
    private static double[][] distance; //所有距离数据
    private static ArrayList<int[]> combiList = new ArrayList<int[]>();
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); //村民的户数
        int m = sc.nextInt(); //备选邮局数
        int k = sc.nextInt(); //要建邮局数
        int[] nArrX = new int[n]; //村民家坐标
        int[] nArrY = new int[n]; 
        int[] mArrX = new int[m]; //备选邮局坐标
        int[] mArrY = new int[m];
        for(int i = 0; i < n; i++){ //输入坐标
            nArrX[i] = sc.nextInt();
            nArrY[i] = sc.nextInt();
        }
        for(int i = 0; i < m; i++){
            mArrX[i] = sc.nextInt();
            mArrY[i] = sc.nextInt();
        }
        distance = new double[n][m]; //村民家与备选邮局间的距离
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                distance[i][j] = sqrt(pow(nArrX[i]-mArrX[j], 2) + pow(nArrY[i]-mArrY[j], 2));
            }
        }
        combiArr = new int[k];
        combination(m-1, k, 0);
        int[] best = findLeast(n);
        for(int i = best.length-1; i >= 0; i--){
            System.out.print((best[i]+1) + " ");//运算时编号为0~m-1,加上为题设
        }
    }

    //找出所有组合
    private static void combination(int mMax, int k, int kMax){ 
        if(k==1){
            for(int i = mMax; i >= 0; i--){
                combiArr[kMax] = i;
                int[] temp = Arrays.copyOf(combiArr, combiArr.length);//不能直接add原数组
                combiList.add(temp);
            }
        }
        else{
            for(int i = mMax; i >= k-1; i--){
                combiArr[kMax] = i;
                combination(i-1, k-1, kMax+1);
            }
        }
    }

    //找出最短路径的组合
    private static int[] findLeast(int n){
        double sumLength = 0;
        int[] best = combiList.get(0);
        int[] temp;
        double[] tempEvery = new double[best.length];
        for(int i = 0; i < n; i++){
            for(int k = 0; k < best.length; k++){
                tempEvery[k] = distance[i][best[k]];
            }
            Arrays.sort(tempEvery);
            sumLength += tempEvery[0];//加上到备选邮局的最小距离
        }
        double shortest = sumLength;
        for(int j = 1; j < combiList.size(); j++){
            temp = combiList.get(j);
            sumLength = 0;
            for(int i = 0; i < n; i++){
                for(int k = 0; k < temp.length; k++){
                    tempEvery[k] = distance[i][temp[k]];
                }
                Arrays.sort(tempEvery);
                sumLength += tempEvery[0];
            }
            if(sumLength < shortest){
                shortest = sumLength;
                best = temp;
            }
        }
        return best;
    }
}




  

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2014-12-08 17:54  包清骏  阅读(382)  评论(0编辑  收藏  举报