zoukankan      html  css  js  c++  java
  • Java实现 蓝桥杯 历届试题 邮局

    问题描述
      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。

    import java.util.Scanner;
    
    public class Main {
        public static int n, m, k;
        public static double[][] distance;    //distanc[i][j]表示第i个村庄到第j个邮局的直线距离
        public static int[] answer;  //存放最终选中的k个邮局编号
        public static double minSum;   //表示选中k个邮局的最小距离和
        
        public void init() {
            distance = new double[n + 1][m + 1];
            answer = new int[k + 1];
            minSum = Double.MAX_VALUE;
        }
        
        /*
         * 参数count:表示已经选中的邮局个数
         * 参数current:表示DFS目前遍历到的邮局编号
         * 参数minDis:minDis[i]表示村庄i到已选中邮局中的最短距离
         * 参数tempAns:存放目前遍历过程中已经选中的邮局编号
         */
        public void dfs(int count, int current, double[] minDis, int[] tempAns) {
            if(count == k) {  //当已经选中k个邮局时
                double tempSum = 0;
                for(int i = 1;i <= n;i++)
                    tempSum += minDis[i];
                if(tempSum < minSum) {
                    minSum = tempSum;
                    for(int i = 1;i <= k;i++)
                        answer[i] = tempAns[i];
                }
                return;
            } else if(k - count <= m - current && current <= m) { //表示在剩下未选中的邮局个数多于还需要选中的邮局个数
                boolean judge = false;   //用于判断当前选中的邮局current+1是否符合要求
                double[] minDis1 = new double[n + 1];  //用于保存当前minDis数组中值
                for(int i = 1;i <= n;i++)
                    minDis1[i] = minDis[i];
                for(int i = 1;i <= n;i++) {
                    if(minDis[i] > distance[i][current + 1]) {
                        minDis[i] = distance[i][current + 1];
                        judge = true;
                    }
                }
                tempAns[count + 1] = current + 1;
                if(judge == true)  //邮局current + 1符合要求,选中个数加1继续搜索
                    dfs(count + 1, current + 1, minDis, tempAns);
                dfs(count, current + 1, minDis1, tempAns); //直接舍弃邮局current+1,进行下一次搜索
            }
        }
            
        public static void main(String[] args) {
            Main test = new Main();
            Scanner in = new Scanner(System.in);
            n = in.nextInt();
            m = in.nextInt();
            k = in.nextInt();
            test.init();
            double[][] point = new double[n + 1][2];   //存放n个村庄的位置坐标
            for(int i = 1;i <= n;i++) {
                point[i][0] = in.nextDouble();   //村庄横坐标
                point[i][1] = in.nextDouble();   //村庄纵坐标
            }
            for(int j = 1;j <= m;j++) {
                double x = in.nextDouble();      //邮局横坐标
                double y = in.nextDouble();      //邮局纵坐标
                for(int i = 0;i <= n;i++)       //计算1~n村庄到邮局j的直线距离
                    distance[i][j] = Math.sqrt((point[i][0]-x)*(point[i][0]-x) + 
                            (point[i][1]-y)*(point[i][1]-y));
            }
            int[] tempAns = new int[k + 1];
            double[] minDis = new double[n + 1]; //minDis[i]表示第i个村庄到已选中的邮局中的最小距离
            for(int i = 1;i <= n;i++)
                minDis[i] = Double.MAX_VALUE;//初始化第i个村庄到选中邮局中最小距离为最大值
            
            test.dfs(0, 0, minDis,  tempAns);
            for(int i = 1;i <= k;i++)
                System.out.print(answer[i]+" ");
        }
    }
    
  • 相关阅读:
    vsftp搭建
    进程管理相关命令(15 个)
    系统管理与性能监视命令 (9 个)
    系统权限及用户授权相关命令(4 个)
    用户管理命令(10个命令)
    深入网络操作命令(9条命令)
    查看系统用户登陆信息的命令(7 个)
    查看文件及内容处理命令(21个命令)
    有关磁盘与文件系统的命令(16个命令)
    linux kernel bisops.h
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13077709.html
Copyright © 2011-2022 走看看