模拟退火 poj 1379

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

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

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

算法流程(转载)


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.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值