【模拟退火】CF2C Commentator problem

简介: 笔记

题目描述


The Olympic Games in Bercouver are in full swing now. Here everyone has their own objectives: sportsmen compete for medals, and sport commentators compete for more convenient positions to give a running commentary. Today the main sport events take place at three round stadiums, and the commentator’s objective is to choose the best point of observation, that is to say the point from where all the three stadiums can be observed. As all the sport competitions are of the same importance, the stadiums should be observed at the same angle. If the number of points meeting the conditions is more than one, the point with the maximum angle of observation is prefered.


Would you, please, help the famous Berland commentator G. Berniev to find the best point of observation. It should be noted, that the stadiums do not hide each other, the commentator can easily see one stadium through the other.


输入格式


The input data consists of three lines, each of them describes the position of one stadium. The lines have the format x,y,r , where ( x,y ) are the coordinates of the stadium’s center  ( -10^3 <= x,y<=10^3 ) is its radius. All the numbers in the input data are integer, stadiums do not have common points, and their centers are not on the same line.


输出格式


Print the coordinates of the required point with five digits after the decimal point. If there is no answer meeting the conditions, the program shouldn’t print anything. The output data should be left blank.


具体思路

题意: 要求找到一个点,使得到三个圆的两切线张角相同,取最大张角的那个点输出,没有则不输出。


既然是模拟退火,那主要的就是两个部分:


估价函数

参数配置

那么对于评估函数的选定为:

1.png2.png

具体实现:

double evaluation(node &A) {
  double t[3], delta[3], res = 0;
  for (int i = 0; i < 3; i++)
    t[i] = distance(A, p[i]) / p[i].r;
  for (int i = 0; i < 3; i++) {
    delta[i] = t[i] - t[(i + 1) % 3];
    res += delta[i] * delta[i];
  }
  return res * 1e9;
}

3.png4.png

不过为了洛谷 AC 时刻的 🎉 还是很值得的。

5.png

那么附上全部代码:


代码实现

众所周知,rand()是个玄学

实验得: 1 / 2 {1 / 2}1/2 的概率通过

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
const double eps = 1e-14;
const double gradient = 0.996;
struct Point {
  double x, y, r;
} p[N];
struct node {
  double x, y;
} nowNode, ansNode;
double MINX = 1e9, MAXX = -1e9, MINY = 1e9, MAXY = 1e9;
double distance(node &A, Point &B) {
  return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
double evaluation(node &A) {
  double t[3], delta[3], res = 0;
  for (int i = 0; i < 3; i++)
    t[i] = distance(A, p[i]) / p[i].r;
  for (int i = 0; i < 3; i++) {
    delta[i] = t[i] - t[(i + 1) % 3];
    res += delta[i] * delta[i];
  }
  return res * 1e9;
}
node groop;
void SA() {
  nowNode = groop;
  double nowDelta = evaluation(nowNode);
  double T = 1e5;
  while(T > eps) {
    // double nowx = nowNode.x + (((rand() << 1) - RAND_MAX) > 0 ? -1 : 1) * T * rand() * 1.0 / RAND_MAX;
    // double nowy = nowNode.y + (((rand() << 1) - RAND_MAX) > 0 ? -1 : 1) * T * rand() * 1.0 / RAND_MAX;
    double nowx = nowNode.x + ((rand() << 1) - RAND_MAX) * T;
    double nowy = nowNode.y + ((rand() << 1) - RAND_MAX) * T;
    if(fabs(nowx) > 1000 || fabs(nowy) > 1000 || \
    nowx < MINX || nowx > MAXX || nowy < MINY || nowy > MAXY) {
      T *= gradient; 
      continue;
    }
    node tmpNode = {nowx, nowy};
    double tmpDelta = evaluation(tmpNode);
    double delta = tmpDelta - nowDelta;
    if(delta < 0) {
      nowNode = tmpNode;
      nowDelta = tmpDelta;
      ansNode = nowNode;
    } else if(exp(-delta / T) * RAND_MAX > 1.0 * rand()) nowNode = tmpNode, nowDelta = tmpDelta;
    T *= gradient;
  }
}
void solve() {
  srand(time(NULL));
  for (int i = 0; i < 3; i++) {
    cin >> p[i].x >> p[i].y >> p[i].r;
    nowNode.x += p[i].x / 3;
    nowNode.y += p[i].y / 3;
    MINX = min(MINX, p[i].x);
    MAXX = max(MAXX, p[i].x);
    MINY = min(MINY, p[i].y);
    MAXY = max(MAXY, p[i].y);
  }
  groop = nowNode;
  for(int i = 0; i < 300; i++) SA();
  if(evaluation(ansNode) < 1e-5) {
      printf("%.5lf %.5lf\n", \
      fabs(ansNode.x) < 1e-5 ? fabs(ansNode.x): ansNode.x, \
      fabs(ansNode.y) < 1e-5 ? fabs(ansNode.y): ansNode.y);
    }
}
int main() {
  solve();  
  return 0;
}
相关文章
|
1月前
|
算法 数据挖掘
Sentieon | 每周文献-Population Sequencing-第三十四期
Sentieon | 每周文献-Population Sequencing-第三十四期
29 0
|
8月前
|
人工智能 资源调度 自动驾驶
Markov Decision Process,MDP
马尔可夫决策过程(Markov Decision Process,MDP)是一种用于描述决策者在马尔可夫环境中进行决策的数学模型。它由四个核心要素组成:状态(State)、动作(Action)、转移概率(Transition Probability)和奖励(Reward)。在 MDP 中,智能体(Agent)需要在给定的状态下选择一个动作,然后根据状态转移概率和奖励更新状态,最终目标是最大化累积奖励。
58 4
|
10月前
|
计算机视觉 Python
Ha-NeRF: Hallucinated Neural Radiance Fields in the Wild 代码复现与解读
Ha-NeRF: Hallucinated Neural Radiance Fields in the Wild 代码复现与解读
137 0
|
机器学习/深度学习 存储 算法
YOLOv5的Tricks | 【Trick7】指数移动平均(Exponential Moving Average,EMA)
这篇博客主要用于整理网上对EMA(指数移动平均)的介绍,在yolov5代码中也使用了这个技巧,现对其进行归纳。
1523 1
YOLOv5的Tricks | 【Trick7】指数移动平均(Exponential Moving Average,EMA)
AtCoder Beginner Contest 221 D - Online games(差分 离散化 区间)
AtCoder Beginner Contest 221 D - Online games(差分 离散化 区间)
111 0
CF1567D. Expression Evaluation Error(思维 贪心)
CF1567D. Expression Evaluation Error(思维 贪心)
49 0
ICPC North Central NA Contest 2018 G . Tima goes to Xentopia(最短路 空间优化 剪枝)
ICPC North Central NA Contest 2018 G . Tima goes to Xentopia(最短路 空间优化 剪枝)
62 0
[North Central NA Contest 2018] Rational Ratio | 规律 细节模拟
Description Every (positive) rational number can be expressed as a ratio of two (positive) integers. However, in decimal form, rational numbers often have an infifinitely repeating pattern, e.g., 1/7 = 0.142857142857142857…
96 0
[North Central NA Contest 2018] Rational Ratio | 规律 细节模拟
|
数据可视化 算法
Paper:《Greedy Function Approximation: A Gradient Boosting Machine贪心函数逼近:梯度提升机器模型》翻译与解读—PDP来源
Paper:《Greedy Function Approximation: A Gradient Boosting Machine贪心函数逼近:梯度提升机器模型》翻译与解读—PDP来源