codeforces 2C Commentator problem

来源:互联网 发布:淘宝快递单模板 编辑:程序博客网 时间:2024/04/28 14:34
C. Commentator problem
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard output

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.

Input

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 ( -  103 ≤ x,  y ≤ 103), and r (1 ≤ r  ≤ 103) 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.

Output

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.

题目大意是有3个圆,求一点a,使点a对三个圆的视角相等(过a做圆的两条切线,此两切线的夹角即为视角)。若有多点视角相等,则取视角最大的点。

设三个圆的半径分别为r1,r2,r3。设点a到三个圆的圆心距离分别为d1,d2,d3。

即目标是2*arcsin(r1/d1) = 2*arcsin(r2/d2) = 2*arcsin(r3/d3)。即r1/d1 = r2/d2 = r3/d3

那么这就是解析几何的问题了,就是列出坐标系,一顿算呗。应该很难算。但是算出公式直接给程序就行了。

看到网上还有一种方法,就是一种随机的算法。

从一个初始的解开始逐步逼近最优解。

当迭代了若干步之后,估值函数的值仍然较大时,则不存在解。

最开始,我取的估值函数cost = fabs(ang1-ang2) + fabs(ang2-ang3) + fabs(ang3-ang1). 其中ang1 ang2 ang3就是用arcsin求出来的。

这样的问题就是可能会带来比较大的误差,因为要计算的arcsin的值可能很小,所以一开始一直都没法AC。

后来我把估值函数cost 取为cost = (d1/r1-d2/r2)^2 + (d2/r2-d3/r3)^2 + (d3/r3-d1/r1)^2,效果就好一些,就AC了。

总而言之呢,这种随机算法的题目就是很蛋疼了。但是在蛋疼的基础上,还是可以采取一些办法去减小误差的。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <stack>#include <map>#include <string>using namespace std;struct pt {    double x;    double y;    double r;};pt mkp(double x, double y) {    pt ret;    ret.x = x;    ret.y = y;    return ret;}double dis(pt a, pt b) {    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));}double cost(pt *p, double x, double y) {    double ang[3];    for (int i = 0; i < 3; i++) ang[i] = dis(p[i], mkp(x, y)) / p[i].r;    double diff[3];    for (int i = 0; i < 3; i++) diff[i] = ang[i] - ang[(i+1)%3];    double ret = 0;    for (int i = 0; i < 3; i++) ret += diff[i] * diff[i];    return ret;}const int dx[] = {0, 1, -1, 0};const int dy[] = {1, 0, 0, -1};const double err = 1e-6;int main() {    pt p[3];    for (int i = 0; i < 3; i++) scanf("%lf %lf %lf", &(p[i].x), &(p[i].y), &(p[i].r));        pt ans;    ans.x = (p[0].x + p[1].x + p[2].x) / 3.0;    ans.y = (p[0].y + p[1].y + p[2].y) / 3.0;    double ncost = cost(p, ans.x, ans.y);    pt tmp;    double step = 1.0;    bool flag = false;    for (int i = 0; i < 300000 && ncost > err; i++) {        flag = false;        for (int k = 0; k < 4; k++) {            tmp.x = ans.x + step * ((double)dx[k]);            tmp.y = ans.y + step * ((double)dy[k]);            if (ncost > cost(p, tmp.x, tmp.y)) {                ncost = cost(p, tmp.x, tmp.y);                ans = tmp;                flag = true;            }        }        if (!flag) step *= 0.5;    }    if (cost(p, ans.x, ans.y) <= err) printf("%.5lf %.5lf\n", ans.x, ans.y);    return 0;}


0 0
原创粉丝点击