模拟退火 poj 1379

矩阵中找一点使该点到各已知陷阱中最近的最远。

如果是神牛,自然可以用voronoi图

但是,由于较优值比较离散,所以编程复杂度较低,但期望得分较高的模拟退火显然更适用。

算法流程(转载)

模拟退火 poj 1379_第1张图片

p,l一开始我取的100,tle了,后来看别人取得20、25才改小的。

根据程序不同,要适当调整退火程度和下界

跑得很慢,该算法需要rp啊

const maxp=30;
      maxt=0.2;
      maxl=30;
var f,x,y,xx,yy:array[1..1000]of real;
    n,p,i:longint;
    ansx,ansy,ans,t:real;
    maxx,maxy:longint;
function dist(x,y,z,p:real):real;
begin
 exit(sqr(x-z)+sqr(y-p))
end;
function test(xx,yy:real):real;
var i:longint;
    cos:real;
begin
 test:=maxlongint;
 for i:=1 to n do begin
  cos:=dist(x[i],y[i],xx,yy);
  if cos<test then test:=cos
 end
end;
procedure init;
var i,j:longint;
    x1,y1,x2,y2,y3,y4,mx,my,mm,cos:real;
begin
 readln(maxx,maxy,n);
 maxx:=maxx*10;maxy:=maxy*10;
 for i:=1 to n do begin readln(x[i],y[i]);x[i]:=x[i]*10;y[i]:=y[i]*10 end;
 p:=maxp;
 ansx:=1;ansy:=1;ans:=0;
 for i:=1 to p do begin xx[i]:=1+random(maxx);yy[i]:=1+random(maxy);f[i]:=test(xx[i],yy[i]) end;
 t:=dist(maxx,maxy,0,0);
 while t>maxt do begin
  for i:=1 to p do begin
   mx:=0;my:=0;mm:=0;
   for j:=1 to maxl do begin
    x1:=-10+random(21);y1:=10-sqr(x1);y2:=-y1;
    x1:=x1*t;y1:=y1*t;y2:=y2*t;
    x2:=x1+xx[i];y3:=y1+yy[i];y4:=y2+yy[i];
    if (x2>=0)and(x2<=maxx) then begin
     if (y3>=0)and(y3<=maxy) then begin
      cos:=test(x2,y3);
      if cos>mm then begin mm:=cos;mx:=x2;my:=y3 end
     end;
     if (y4>=0)and(y4<=maxy) then begin
      cos:=test(x2,y4);
      if cos>mm then begin mm:=cos;mx:=x2;my:=y4 end
     end
    end
   end;
   if mm>f[i] then begin f[i]:=mm;xx[i]:=mx;yy[i]:=my end;
   if f[i]>ans then begin ans:=f[i];ansx:=xx[i];ansy:=yy[i] end;
  end;
  t:=t*0.8
 end;
 writeln('The safest point is (',ansx/10:0:1,', ',ansy/10:0:1,').')
end;
begin
 randomize;
 readln(i);
 for i:=1 to i do init
end.


你可能感兴趣的:(编程,算法,Random)