POJ 1379 Run Away

Problem

POJ

给定n个危险点,在一个给定矩形区域上找到一点,使得其离最近的危险点的距离最大。
n<=1000

Solution

你会发现不好二分答案,于是就可以随机化。

对于这个题目,对于每个危险点的距离就相当与形成了一个波纹一样的圆向外扩散,我们可以将危险的点理解为一个山顶。而当这些圆相遇时,就会汇在一起成为一条山谷,答案就在山谷中,这就是题目所对应的等高线地形图。
随机化30个点,设delta为每一次的步长,每次的操作就是,以此点为圆心,以这个步长为半径作一个圆,再随机化30个角度theta,得到下次的点,然后根据我们之前画的等高线地形图,我们会容易找到山谷,而且随机了30个点,所以其实也可以不以一定概率接受较差解。我们的点就会接近山谷,然后沿着山谷旁向更低的地方游走。。

那个srand里面的值,可能填你的生日或者幸运数就行,theta要迷之乘10,增大角度的离散程度吧可能是

Code

#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const double INF=1e20,eps=1e-3,pi=acos(-1.0);
int z,x,y,n,ans;
double tmp,tdis,dx,dy,delta,theta,dis[40];
struct data{
    double x,y;
    data(){}
    data(double _x,double _y){x=_x;y=_y;}
    data operator - (const data &t){return data(x-t.x,y-t.y);}
    inline double dis(){return sqrt(x*x+y*y);}
}p[1010],t[40],nxt;
inline double min(double x,double y){return x<y?x:y;}
double randf(){return (rand()%1000+1)*1.0/1000.0;}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    srand();
    scanf("%d",&z);
    while(z--)
    {
        scanf("%d%d%d",&x,&y,&n);
        for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
        for(int i=1;i<=30;i++)
        {
            t[i].x=randf()*x;t[i].y=randf()*y;dis[i]=INF;
            for(int j=1;j<=n;j++) dis[i]=min(dis[i],(t[i]-p[j]).dis());
        }
        delta=(1.0*(x>y?x:y))/(sqrt(n*1.0));
        while(delta>eps)
        {
            for(int i=1;i<=30;i++)
            {
                t[0]=t[i];
                for(int j=1;j<=30;j++)
                {
                    theta=randf()*pi*10;
                    dx=delta*cos(theta);dy=delta*sin(theta);
                    nxt.x=t[0].x+dx;nxt.y=t[0].y+dy;tdis=INF;
                    if(nxt.x<0||nxt.x>x||nxt.y<0||nxt.y>y) continue;
                    for(int k=1;k<=n;k++) tdis=min(tdis,(nxt-p[k]).dis());
                    if(tdis>dis[i]){dis[i]=tdis;t[i]=nxt;}
                }
            }
            delta*=0.8;
        }
        ans=0;
        for(int i=1;i<=30;i++)
          if(dis[i]>dis[ans])
            ans=i;
        printf("The safest point is (%.1lf, %.1lf).\n",t[ans].x,t[ans].y);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值