因为N<=15,所以可以直接暴力求解。
先枚举哪些点要选,之后打一个Prim(或克鲁斯卡尔)算结果。
要注意比率相同时,要取字典序更小的。
代码:
var
a:array[1..15] of longint;
b:array[1..15,1..15] of longint;
d:array[1..15] of longint;
bz:array[1..15] of boolean;
ans:array[1..15] of longint;
bz2:array[1..15] of boolean;
f:array[1..15] of longint;
n,m,i,j,min2,min3,min4:longint;
min,tot,s:real;
procedure dg(t,sum,last:longint);
var
i,j,l:longint;
begin
if t>m then
begin
fillchar(bz2,sizeof(bz2),false);
s:=0;
f[1]:=d[1];
bz2[d[1]]:=true;
for l:=1 to m-1 do
begin
min2:=maxlongint;
for i:=1 to l do
begin
for j:=1 to m do
if (f[i]<>d[j]) and (bz[d[j]]=true) and (bz2[d[j]]=false) then
begin
if b[f[i],d[j]]<min2 then
begin
min2:=b[f[i],d[j]];
min3:=f[i];
min4:=d[j];
end;
end;
end;
if min2<maxlongint then
begin
bz2[min4]:=true;
s:=s+min2;
f[l+1]:=min4;
end;
end;
s:=s/tot;
if s<min then
begin
min:=s;
ans:=d;
end
else
if s=min then
begin
for i:=1 to m do
if ans[i]<d[i] then
exit;
ans:=d;
end;
exit;
end;
for i:=last+1 to n-sum do
begin
d[t]:=i;
bz[i]:=true;
tot:=tot+a[i];
dg(t+1,sum-1,i);
tot:=tot-a[i];
bz[i]:=false;
end;
end;
begin
assign(Input,'ratio.in'); reset(Input);
assign(Output,'ratio.out'); rewrite(Output);
readln(n,m);
for i:=1 to n do
read(a[i]);
for i:=1 to n do
for j:=1 to n do
read(b[i,j]);
min:=maxlongint;
dg(1,m-1,0);
for i:=1 to m do
write(ans[i],' ');
writeln;
close(Input); close(Output);
end.