[POJ 1379] Run Away

题目描述:

给出一块平面,给出N个点,求平面内的点距离这些点最小距离最大是多少

题目分析:

本题为模拟退火的裸题。
模拟退火详解
我们枚举角度,随机点,温度为半径,随机30组点进行求解

题目链接:

POJ 1379

Ac 代码:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cmath>
#define PI std::acos(-1.0)
const int Num=30;
const int maxm=1010;
const double eps=1e-3;
const double r=0.8;
const double inf=1e9+7;
struct node{
    double x,y;
}a[maxm],b[maxm];
double dis[maxm];
inline double distance(double x1,double y1,double x2,double y2)
{
    return std::sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); 
}
inline void work()
{
    int n,X,Y;
    scanf("%d%d%d",&X,&Y,&n);
    for(int i=1;i<=n;i++)
     scanf("%lf%lf",&a[i].x,&a[i].y);
    for(int i=1;i<=Num;i++)
    {
        dis[i]=inf;
        b[i].x=(double)(rand()%1000+1)/1000.0*X;
        b[i].y=(double)(rand()%1000+1)/1000.0*Y;//随机点值 
        for(int j=1;j<=n;j++)
         dis[i]=std::min(dis[i],distance(b[i].x,b[i].y,a[j].x,a[j].y));
    }
    double T=(double)std::max(X,Y)/(double)std::sqrt(1.0*n);//初始温度 
    while(T>eps)
    {
        for(int i=1;i<=Num;i++)
        {
            double xx=b[i].x,yy=b[i].y;
            for(int j=1;j<=Num;j++)
            {
                double angle=(double)(rand()%1000+1)/1000.0*2.0*PI;//枚举角度 
                double bx=T*std::cos(angle);
                double by=T*std::sin(angle);
                double newx=xx+bx,newy=yy+by;
                if(newx>X||newy>Y||newx<eps||newy<eps) continue;
                double nowdis=inf;
                for(int k=1;k<=n;k++) nowdis=std::min(nowdis,(double)distance(newx,newy,a[k].x,a[k].y));
                if(nowdis>dis[i])
                {
                    dis[i]=nowdis;
                    b[i].x=newx,b[i].y=newy;
                }
            }
        }
        T*=r;//降温 
    }
    int ans=0;
    double dmax=-1;
    for(int i=1;i<=Num;i++)
    if(dmax<dis[i]) dmax=dis[i],ans=i;
    printf("The safest point is (%.1lf, %.1lf).\n",b[ans].x,b[ans].y);
}
int main()
{
    srand((unsigned)time(NULL));
    int t;
    scanf("%d",&t);
    while(t--)
     work();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值