蓝桥杯真题: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
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; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。