【模拟退火】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;
}
相关文章
|
6月前
|
算法 数据挖掘
Sentieon | 每周文献-Population Sequencing-第二十三期
Sentieon | 每周文献-Population Sequencing-第二十三期
41 1
|
6月前
|
算法 数据挖掘
Sentieon | 每周文献-Population Sequencing-第三十四期
Sentieon | 每周文献-Population Sequencing-第三十四期
45 0
|
计算机视觉 Python
Ha-NeRF: Hallucinated Neural Radiance Fields in the Wild 代码复现与解读
Ha-NeRF: Hallucinated Neural Radiance Fields in the Wild 代码复现与解读
174 0
AtCoder Beginner Contest 221 D - Online games(差分 离散化 区间)
AtCoder Beginner Contest 221 D - Online games(差分 离散化 区间)
130 0
CF1567D. Expression Evaluation Error(思维 贪心)
CF1567D. Expression Evaluation Error(思维 贪心)
59 0
|
机器学习/深度学习
AtCoder Beginner Contest 218 F - Blocked Roads (最短路径还原 思维)
AtCoder Beginner Contest 218 F - Blocked Roads (最短路径还原 思维)
99 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…
107 0
[North Central NA Contest 2018] Rational Ratio | 规律 细节模拟
|
算法 搜索推荐
模拟退火(SA)算法求解Max-Minsum Dispersion Problem(附代码及详细注释)
模拟退火(SA)算法求解Max-Minsum Dispersion Problem(附代码及详细注释)
238 0
模拟退火(SA)算法求解Max-Minsum Dispersion Problem(附代码及详细注释)
|
机器学习/深度学习 算法 Python
ML之NN:利用神经网络的BP算法解决XOR类(异或非)问题(BP solve XOR Problem)
ML之NN:利用神经网络的BP算法解决XOR类(异或非)问题(BP solve XOR Problem)
ML之NN:利用神经网络的BP算法解决XOR类(异或非)问题(BP solve XOR Problem)
|
语音技术 机器学习/深度学习 开发者
语音顶会Interspeech 论文解读|Towards A Fault-tolerant Speaker Verification System: A Regularization Approach To Reduce The Condition Number
Interspeech是世界上规模最大,最全面的顶级语音领域会议,本文为Siqi Zheng, Gang Liu, Hongbin Suo, Yun Lei的入选论文
语音顶会Interspeech 论文解读|Towards A Fault-tolerant Speaker Verification System: A Regularization Approach To Reduce The Condition Number