百度地图有自己的一套坐标系(你可以把它看作一个笛卡尔坐标系),在这套坐标系里,一个标准单位为1km。而在这坐标系上针对地理信息进行标注的数据,大多数时候是通过购买的方式完成的。为了节约数据更新的成本,数据组里的鑫哥想出了一个好主意——自己测数据。
鑫哥按照他的预想开始实验;在每组试验中,鑫哥选取了三个已经被准确标注在百度地图的坐标系里的移动运营商的基站作为信号接收点(这里可以准确的得到信号的接收时间信息)。当信号接收点附近的用户手机签到时,三个信号接收点就会先后接收到这个信号,并可以准确的知晓接收到信号的时间(将第一个信号点接收到信号的时间记为0秒时刻)。由此,我们就可以确定用户手机签到的位置的在地图的准确坐标了。
现在已知以下数据:
1.三个信号接收点在百度地图坐标系中的具体坐标(x1,y1), (x2,y2), (x3,y3);
2.三个信号点得到用户发出的信号的时间t1, t2, t3(t1, t2, t3 ≥ 0),单位s; t1, t2, t3至少有一个数为0;
3.信号的转播速度C,单位m/s;
请帮助鑫哥写个程序,计算下用户发出信号的位置在百度地图坐标系内的坐标(这个点是唯一的)。
1000
0 1 1 1 2 1
0 0.6 1.6
1000
0 0 0 1 1 0
0.4142135 0 0
1000
0 0 1 0 2 1
0 0.414213562373 1
1000
0 0 0 -1 0 1
0 0 1
1000
0 0 0 1 0 -1
0 1 0
1000
0 0 1 0 -1 0
0 1 0
1000
0 0 -1 0 1 0
0 0 1
100
0 0 0 1 1 0
0 10 10
0
Case 1:
0.200000 1.000000
Case 2:
1.000000 1.000000
Case 3:
0.000000 1.000000
Case 4:
0.000000 -0.500000
Case 5:
0.000000 -0.500000
Case 6:
-0.500000 0.000000
Case 7:
-0.500000 0.000000
Case 8:
0.000000 0.000000
实现代码:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; double x[4], y[4], t[4]; void solve(int i , int j , int k) { double x2, y2, x3, y3, l2, l3 , sum , fai , cita , r , m , n; //cita x2 = x[j] -x[i] , y2 = y[j] -y[i]; x3 = x[k] -x[i] , y3 = y[k] -y[i]; l2 = t[j] -t[i] , l3 = t[k] -t[i]; m = x2*x2 + y2*y2 - l2*l2 , n = x3*x3 + y3*y3 - l3*l3; // 得到方程 a*sin(cita) + b*cos(cita) = -c double a = m*y3-n*y2 ; //sin(cita)的系数 double b = m*x3-n*x2 ; //cos(cita)的系数 double c = m * l3 - n * l2; // 得到方程 sin(cita+fai) = -c/(sqrt(a*a+b*b)) fai = atan2(b, a) ; //先求出角度fai sum = asin(- c/sqrt(a*a+b*b+1e-15)); //通过反正弦函数求出cita+fai的角度和 cita = sum - fai; // 此时cita是一个锐角 if (abs(m)>abs(n)) r = m/(l2 + x2 *cos(cita) + y2 * sin(cita))/2; else r = n/(l3 + x3 *cos(cita) + y3 * sin(cita))/2; if(r < 0) { sum = - sum + 3.141592653579; //r<0,说明不能是锐角,应该是个钝角 cita = sum - fai; if (abs(m)>abs(n)) r = m/(l2 + x2 *cos(cita) + y2 * sin(cita))/2; else r = n/(l3 + x3 *cos(cita) + y3 * sin(cita))/2; } printf("%.6f %.6f\n", r * cos(cita) + x[i], r * sin(cita) + y[i]); } int main(void) { int num = 1; double c; while(scanf("%lf", &c)!=EOF) { c/=1000; if (abs(c) < 1e-6) break; scanf("%lf %lf %lf %lf %lf %lf", x, y, x+1, y+1, x+2, y+2); scanf("%lf %lf %lf", t, t+1, t+2); printf("Case %d:\n", num++); t[0] *= c; t[1] *= c; t[2] *= c; solve(0, 1, 2); } return 0; }