1 条题解

  • 0
    @ 2025-4-17 15:34:33

    题意:在给定矩阵范围内找一个点,该点距离矩阵内所有点的最小值最大,

    在算法书看到这道题,算法为 模拟退火法 在书上看过,又看别人的写法,先找20个随机种子,然后逐步更新,最后取最优解。

    具体看代码:

    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include<math.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define eps 1e-8
    #define pi acos(-1.0)//3.14
    typedef long long ll;
    struct node
    {
      double x,y,dis;
    } a[2000],b[100],ans;
    int n,X,Y;
    double dis(node c)
    {
      double sum=1e8;
      for (int i=1; i<=n; ++i)
      {
        double dd=sqrt((c.x-a[i].x)*(c.x-a[i].x)+(c.y-a[i].y)*(c.y-a[i].y));
        if(sum>dd)sum=dd;//找到最小距离
      }
      return sum;
    }
    void Solve()
    {
      for (int i=1; i<=20; ++i)//预20个并行解状态处理
      {
        b[i].x=rand()%X+1,b[i].y=rand()%Y+1;//生成随机位置
        b[i].dis=dis(b[i]);//找到位置最小距离
      }
      node t;
      for (double i=max(X,Y); i>=1e-2; i*=0.9)//初始温度 再温度未退至足够低 退火
        for (int j=1; j<=20; j++)//枚举每个状态
          for (int k=1; k<=20; k++)//随机调节20个方向 依次迭代
          {
            double ran=rand();
            t.x=b[j].x+cos(ran)*i;//取出第j个解状态
            t.y=b[j].y+sin(ran)*i;//+随机方向
            if (0>t.x || t.x>X || 0>t.y || t.y>Y)
              continue;//若t在界外
            t.dis=dis(t);
            if (t.dis>b[j].dis) b[j]=t;//更新最大距离状态
          }
      ans.dis=-1;
      for (int i=1; i<=20; ++i)if (ans.dis<b[i].dis) ans=b[i];//找出最大距离
    }
     
    int main()
    {
      int test;
      scanf("%d",&test);
      while (test--)
      {
        scanf("%d %d %d",&X,&Y,&n);//矩阵XY
        for (int i=1; i<=n; i++)
          scanf("%lf %lf",&a[i].x,&a[i].y);//矩阵内的点
        Solve();
        printf("The safest point is (%.1f, %.1f).\n",ans.x,ans.y);
      }
      return 0;
    }
    • 1

    信息

    ID
    380
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者