题目
A公司想在N个城市中选择M个来开维修店,而购买了A公司产品的人如果要维修,可以送到最近的维修店。A公司想知道,选择哪些城市开维修店可以使得离维修店最远的那个城市离维修店的距离尽量小。给出N个城市的坐标(城市的坐标是唯一的),你能帮A公司求出这个最小的距离吗?
Input
输入的第一行包含两个整数,分别是城市数N以及维修店数M。
接下来的N行各包含两个数,分别是每个城市的X坐标和Y坐标。
Output
输出只有一行,包含一个小数,为所求的最小距离,保留2位有效数字。
Sample Input
4 2
0 0
1 1
2 4
3 9
Sample Output
3.16
对于所有的数据,1 ≤ M ≤ N ≤ 20,-1000 ≤ X,Y ≤ 1000。
题解
从数据(1 ≤ M ≤ N ≤ 20)大小可以看出,题目可以用搜索完成。
因为要在n个城市中选择m个开维修店,所以应该是要求从n个数中选m个的组合,在每个组合再求距离。
组合的求法
dep表示选了dep个数,pre表示在n个数中选到第pre个数。
当dep>m时,就求最大值(注意选中的点不能算进去)并和答案比较,退出
这时就可以用选中的点i(a[i,j])来更新d[j](注意选中的点不能算进去),可以用回溯来改变v值
代码
var
n,m,i,j:longint;
ans:real;
t:array[1..20,1..2]of longint;
a:array[1..20,1..20]of real;
v:array[1..20]of boolean;
d:array[1..20]of real;
procedure sea(pre,dep:longint);
var
t:array[1..20]of real;
i,j:longint;
ts:real;
begin
if dep>m then
begin
ts:=0;
for i:=1 to n do
if (not v[i]) and (d[i]>ts) then ts:=d[i];
if ts<ans then ans:=ts;
exit;
end;
for i:=pre+1 to n-(m-dep) do
begin
t:=d;
v[i]:=true;
for j:=1 to n do
if (not v[j]) and (a[i,j]<d[j]) then d[j]:=a[i,j];
sea(i,dep+1);
v[i]:=false;
d:=t;
end;
end;
begin
assign(input,'repair.in');
assign(output,'repair.out');
reset(input);rewrite(output);
readln(n,m);
for i:=1 to n do
readln(t[i,1],t[i,2]);
for i:=1 to n do
for j:=1 to n do
if i<>j then a[i,j]:=sqrt(sqr(t[i,1]-t[j,1])+sqr(t[i,2]-t[j,2]))
else a[i,j]:=maxint;
ans:=maxint;
for i:=1 to n do
d[i]:=maxint;
sea(0,1);
writeln(ans:0:2);
close(input);close(output);
end.