历届试题 邮局
时间限制:1.0s 内存限制:256.0MB
问题描述
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。
思路:直接暴力,搜索m个邮局里面选出k个的组合,然后求其中使得距离和最小的方案。这里面不要全部k个搜完,
在二重循环求当前邮局方案所对应的距离和,而是应该每多安排一个邮局,就更新一下到各村民家的最小距离值,
即 nowdist[nown][j]=min(nowdist[nown-1][j],dist[j][i])(其中nown表示当前已经搜到第nown个邮局,而i表示该邮局尝试的编号)
最后即是求nowdist[k][1]+~~~+nowdist[k][n]的最小值所对应的方案res[1],~~~,res[k]
import java.util.Scanner;
public class Main {
static int i, n, m, k;
static double ans;
static int x[], y[], xpost[], ypost[], ansarr[], res[];
static double dist[][], nowdist[][];
private static void show(int arr[]) {
for (int i = 1; i <= k; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
private static void dfs(int num, int nown, int last) {
if (nown == k + 1) {
double sumdist = 0;
for (int i = 1; i <= n; i++)
sumdist += nowdist[k][i];
if (sumdist < ans) {
ans = sumdist;
ansarr = res.clone();
}
return;
}
for (int i = num; i <= last; i++) {
for (int j = 1; j <= n; j++)
nowdist[nown][j] = nowdist[nown - 1][j] < dist[j][i] ? nowdist[nown - 1][j]
: dist[j][i];
res[nown] = i;
dfs(i + 1, nown + 1, last + 1);
res[nown] = 0;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner reader = new Scanner(System.in);
n = reader.nextInt();
m = reader.nextInt();
k = reader.nextInt();
x = new int[n + 1];
y = new int[n + 1];
xpost = new int[n + 1];
ypost = new int[n + 1];
for (int i = 1; i <= n; i++) {
x[i] = reader.nextInt();
y[i] = reader.nextInt();
}
for (int i = 1; i <= m; i++) {
xpost[i] = reader.nextInt();
ypost[i] = reader.nextInt();
}
ansarr = new int[k + 1];
ans = Integer.MAX_VALUE;
dist = new double[n + 1][m + 1];
res = new int[k + 1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
double xsqr = (x[i] - xpost[j]) * (x[i] - xpost[j]);
double ysqr = (y[i] - ypost[j]) * (y[i] - ypost[j]);
dist[i][j] = Math.sqrt(xsqr + ysqr);
}
nowdist = new double[k + 1][n + 1];
for (int i = 1; i <= n; i++)
nowdist[0][i] = Integer.MAX_VALUE / n;
dfs(1, 1, m - k + 1);
show(ansarr);
}
}