codeforces 2C Commentator problem (1)-- 几何

博客探讨了如何帮助体育评论员G. Berniev找到最佳观察点,以便从该点可以看到三个圆形体育场且视角相等。问题涉及到解决一组包含三个圆的坐标和半径的几何方程,以找到满足条件的点。如果存在多个解,应选择视角最大的那个,这可以通过比较圆心距和半径的比例来确定。博客内容包括了解题思路和可能的解决方案策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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(x,y)到三个圆的圆心距离分别为d1,d2,d3。则r1/d1 = r2/d2 = r3/d3即可,设r1/d1 = r2/d2 = r3/d3=r;则有方程:

(x-x1)^2+(y-y1)^2=(r*d1)^2

(x-x2)^2+(y-y2)^2=(r*d2)^2

(x-x3)^2+(y-y3)^2=(r*d3)^3

那么,三个方程,三个未知数,可以求出x,y,r,解的个数可能是0,1,2,当有2个解(r>0)时,若要视角最大,而场馆半径是一定的,显然离得近的大,即r小的解。要人为直接解出方程求出公式是比较难的,但是可以模拟人为计算过程,不过也是比较繁琐,主要是需要细致。=。=


#include<cstdio>
#include<iostream>
#include<cmath>
#include<iomanip>

using namespace std;

int p[3][2];
int r[3];

int main(){
  int i,j;
  int a[2],b[2],k[2],c[2];
  double xr,yr,xc,yc;
  double af,bf,cf;
  double deta,maxd,mind;
  double rs,x,y;

#if defined(DEBUG)||defined(TEST)
  freopen("data","r",stdin);
#endif

  for(i=0;i<3;i++){
    cin>>p[i][0]>>p[i][1]>>r[i];
  }

#ifdef DEBUG
  for(i=0;i<3;i++){
    cout<<p[i][0]<<"\t"<<p[i][1]<<"\t"<<r[i]<<endl;
  }
#endif

  a[0] = 2*(p[0][0]-p[1][0]);
  a[1] = 2*(p[1][0]-p[2][0]);
  b[0] = 2*(p[0][1]-p[1][1]);
  b[1] = 2*(p[1][1]-p[2][1]);
  k[0] = r[1]*r[1] - r[0]*r[0];
  k[1] = r[2]*r[2] - r[1]*r[1];
  c[0] = p[1][0]*p[1][0] - p[0][0]*p[0][0] + p[1][1]*p[1][1] - p[0][1]*p[0][1];
  c[1] = p[2][0]*p[2][0] - p[1][0]*p[1][0] + p[2][1]*p[2][1] - p[1][1]*p[1][1];
  c[0] = -c[0];
  c[1] = -c[1];

#ifdef DEBUG
  cout<<"a\tb\tk\tc\t"<<endl;
  for(i=0;i<2;i++){
    cout<<a[i]<<"\t"<<b[i]<<"\t"<<k[i]<<"\t"<<c[i]<<endl;
  }
#endif

  if(a[1]*b[0]-a[0]*b[1] == 0){
#ifdef DEBUG
    cout<<"no xr.."<<endl;
#endif
    return 0;
  }

  xr = (double)(k[1]*b[0]-k[0]*b[1])/(a[1]*b[0]-a[0]*b[1]);
  xc = (double)(c[1]*b[0]-c[0]*b[1])/(a[1]*b[0]-a[0]*b[1]);
  yr = (double)(k[1]*a[0]-k[0]*a[1])/(a[0]*b[1]-a[1]*b[0]);
  yc = (double)(c[1]*a[0]-c[0]*a[1])/(a[0]*b[1]-a[1]*b[0]);

#ifdef DEBUG
  cout<<"xr:\t"<<xr<<"\txc:\t"<<xc<<"\tyr:\t"<<yr<<"\tyc:\t"<<yc<<endl;
#endif

  af = xr*xr+yr*yr;
  bf = 2*xc*xr-2*p[1][0]*xr+2*yc*yr-2*p[1][1]*yr-r[1]*r[1];
  cf = xc*xc-2*p[1][0]*xc+p[1][0]*p[1][0]+yc*yc-2*p[1][1]*yc+p[1][1]*p[1][1];
  deta = bf*bf-4*af*cf;

#ifdef DEBUG
  cout<<"af:\t"<<af;
  cout<<"\tbf:\t"<<bf;
  cout<<"\tcf:\t"<<cf;
  cout<<"\tdeta:\t"<<deta<<endl;
#endif

  if(af==0){
    if( 0==bf && 0!=cf ){
#ifdef DEBUG
      cout<<"af=0 , bf=0 , cf!=0"<<endl;
#endif
      return 0;
    }
    if( bf*cf>0 ){
#ifdef DEBUG
      cout<<"bf*cf>0"<<endl;
#endif
      return 0;
    }
    x = xc;
    y = yc;
  }else if(deta<0)
    return 0;
  else{
    deta = sqrt(deta);
    maxd = deta-bf;
    mind = -bf-deta;
#ifdef DEBUG
    cout<<"maxd:\t"<<maxd<<"\tmind:\t"<<mind<<endl;
#endif
    if(mind<0)
      mind = maxd;
    if(maxd<0)
      return 0;
    else{
      rs = mind/2/af;
#ifdef DEBUG
      cout<<rs<<endl;
#endif
      x = xr*rs+xc;
      y = yr*rs+yc;
    }
  }
  cout.setf(ios::fixed);
  cout<< setprecision(5) <<x<<" "<<y<<endl;

  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值