2016蓝桥杯假期任务之《邮局》

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

	static int n, m, k, j, f1, f2;
	static int[][] a = new int[55][2];
	static int[][] b = new int[27][2];
	static int[] c = new int[12];
	static int[] d = new int[55];
	static float[][] yc = new float[27][55];
	static float s = 1000000000;

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int i, j;
		int[] o = new int[12];
		float[] w = new float[55];
		n = input.nextInt();
		m = input.nextInt();
		k = input.nextInt();
		for (i = 1; i <= n; i++) {
			a[i][0] = input.nextInt();
			a[i][1] = input.nextInt();
		}
		for (i = 1; i <= m; i++) {
			b[i][0] = input.nextInt();
			b[i][1] = input.nextInt();
			for (j = 1; j <= n; j++)
				yc[i][j] = (float) Math.sqrt((a[j][0] - b[i][0])
						* (a[j][0] - b[i][0]) + (a[j][1] - b[i][1])
						* (a[j][1] - b[i][1]));
		}
		dfs(0, 1, o, w, 0);
		for (i = 0; i < k; i++)
			System.out.print(c[i] + " ");

	}

	private static void dfs(int t, int i, int o[], float w[], float sum) {
		if (i <= m + 1) {
			if (t == k) {
				if (sum < s) {
					s = sum;
					for (j = 0; j < k; j++)
						c[j] = o[j];
				}
			} else if (i <= m && t < k) {
				float[] ww = new float[55];
				for (j = 1; j <= n; j++)
					ww[j] = w[j];
				dfs(t, i + 1, o, w, sum);
				f1 = 1;
				f2 = 0;
				if (d[i] == 0) {
					o[t] = i;
					if (t > 0) {
						f2 = 1;
						for (j = 1; j <= n; j++) {
							if (ww[j] > yc[i][j]) {
								sum = sum - ww[j] + yc[i][j];
								ww[j] = yc[i][j];
								f1 = 0;
							}
						}
					} else {
						for (j = 1; j <= n; j++) {
							sum += yc[i][j];
							ww[j] = w[j] = yc[i][j];
						}
					}
					if (f1 == 1 && f2 == 1) {
						d[i] = 1;
						dfs(t, i + 1, o, w, sum);
					} else
						dfs(t + 1, i + 1, o, ww, sum);
				}
			}
		}

	}

}

运行结果:

5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2
2 4 




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值