【模拟退火】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;
}
相关文章
CF1342B Binary Period(数学分析)
CF1342B Binary Period(数学分析)
27 0
|
7月前
|
机器学习/深度学习 程序员 数据处理
时间序列分析技巧(一):根据ACF、PACF进行AR、MA、ARMA模型选择
时间序列分析技巧(一):根据ACF、PACF进行AR、MA、ARMA模型选择
|
4月前
|
算法 数据挖掘
【博士每天一篇文献-算法】A pseudo-inverse decomposition-based self-organizing modular echo
本文提出了一种基于伪逆分解的自组织模块化回声状态网络(PDSM-ESN),通过增长-修剪方法和伪逆分解提高学习速度,有效解决了ESN中的不适定问题,并在多个数据集上展示了其优越的预测性能和鲁棒性。
27 1
CF1567D. Expression Evaluation Error(思维 贪心)
CF1567D. Expression Evaluation Error(思维 贪心)
64 0
|
人工智能 BI
CF761D Dasha and Very Difficult Problem(构造 思维)
CF761D Dasha and Very Difficult Problem(构造 思维)
85 0
|
人工智能 BI
CF1169C. Increasing by Modulo(二分)
CF1169C. Increasing by Modulo(二分)
136 0
|
算法
HDU-1050,Moving Tables(不用贪心也AC)
HDU-1050,Moving Tables(不用贪心也AC)
|
算法 搜索推荐
模拟退火(SA)算法求解Max-Minsum Dispersion Problem(附代码及详细注释)
模拟退火(SA)算法求解Max-Minsum Dispersion Problem(附代码及详细注释)
245 0
模拟退火(SA)算法求解Max-Minsum Dispersion Problem(附代码及详细注释)
【1150】Travelling Salesman Problem (25分)【图论】
【1150】Travelling Salesman Problem (25分)【图论】 【1150】Travelling Salesman Problem (25分)【图论】
99 0
|
机器学习/深度学习 算法 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)