首页 > 代码库 > hdu 4998
hdu 4998
http://acm.hdu.edu.cn/showproblem.php?pid=4998
这道题,在比赛的时候看了很久,才明白题目的大意。都怪自己不好好学习英语。后来经过队友翻译才懂是什么意思。
题目大意:二维平面内的物品,把它们绕给定的n个点,逆时针旋转。 现在求通过一个A点,逆时针旋转角度P就能完成这个操作。
问:这个点A的坐标,P的角度。
解题思路:随意找个点t1,绕着n个点旋转得到t2。点A一定在线段t1t2的垂直平分线上。再找一点t3,绕n个点旋转得到t4。
线段t1t2的垂直平分线和线段t3t4的垂直平分线相交一点,这点就是A点。证明过程就不写了,可以画图看看。
旋转的角度是向量At1和向量At2的夹角Θ,或是2∏-Θ
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 using namespace std; 5 6 struct Point{ 7 double x, y; 8 9 Point(double x = 0, double y = 0): x(x), y(y){} 10 }; 11 12 typedef Point Vector; 13 14 const double eps = 1e-10; 15 16 int dcmp(double x){ 17 if(fabs(x) < eps) 18 return 0; 19 return x < 0 ? -1 : 1; 20 } 21 22 bool operator == (Point A, Point B){ 23 return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; 24 } 25 26 Vector operator + (Vector A, Vector B){ 27 return Vector(A.x + B.x, A.y + B.y); 28 } 29 30 Vector operator - (Vector A, Vector B){ 31 return Vector(A.x - B.x, A.y - B.y); 32 } 33 34 Vector operator * (Vector A, double p){ 35 return Vector(A.x * p, A.y * p); 36 } 37 38 Vector operator / (Vector A, double p){ 39 return Vector(A.x / p, A.y / p); 40 } 41 42 double dot(Vector A, Vector B){//点乘 43 return A.x * B.x + A.y * B.y; 44 } 45 46 double length(Vector A){//向量的模 47 return sqrt(dot(A, A)); 48 } 49 50 double angle(Vector A, Vector B){//两个向量的夹角 51 return acos(dot(A, B) / length(A) / length(B)); 52 } 53 54 Vector rotate(Vector A, double rad){//点A绕原点旋转角度为rad 55 return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); 56 } 57 58 Vector normal(Vector A){//向量的法向量 59 double L = length(A); 60 return Vector(-A.y / L, A.x / L); 61 } 62 63 double cross(Vector A, Vector B){//叉乘 64 return A.x * B.y - A.y * B.x; 65 } 66 67 int n; 68 Point p[11]; 69 double ra[11]; 70 71 void input(){ 72 cin>> n; 73 for(int i = 0; i < n; ++i){ 74 cin>> p[i].x>> p[i].y>> ra[i]; 75 if(dcmp(ra[i] - 2 * acos(-1.0)) == 0 || dcmp(ra[i]) == 0){ 76 //当输入的弧度为0或者2π时,都是没用的 77 ra[i] = 0; 78 n--; 79 i--; 80 } 81 } 82 } 83 84 Vector rotate_point(Vector A){//将A点绕n个点旋转 85 for(int i = 0; i < n; ++i){ 86 A = p[i] + rotate(A - p[i], ra[i]); 87 } 88 return A; 89 } 90 91 Vector mid_point(Point A, Point B){//求两点之间的中点 92 return Vector((A.x + B.x) / 2, (A.y + B.y) / 2); 93 } 94 95 Point get_line_intersection(Point P, Vector v, Point Q, Vector w){//两直线求交点,《算法入门经典训练之南》几何 96 Vector u = P - Q; 97 double t = cross(w, u) / cross(v, w); 98 return P + v * t; 99 }100 101 void solve(){102 Point t1[2], t2[2], mid[2], vec[2];103 t1[0].x = -10;104 t1[0].y = -10;105 t1[1].x = -100;106 t1[1].y = -20;107 for(int i = 0; i < 2; ++i){108 t2[i] = rotate_point(t1[i]);109 mid[i] = mid_point(t1[i], t2[i]);110 vec[i] = normal(t1[i] - t2[i]);111 }112 Point ans = get_line_intersection(mid[0], vec[0], mid[1], vec[1]);//答案点A113 double ansp = angle(t1[0] - ans, t2[0] - ans);//旋转角度P114 115 if(cross(t1[0] - ans, t2[0] - ans) < 0){//判断是ansp 还是2π - ansp116 ansp = 2 * acos(-1.0) - ansp;117 }118 119 if(dcmp(ans.x) == 0){//加入答案是-1e-11,如果直接输出就会是-0.0000000000120 ans.x = 0;121 }122 if(dcmp(ans.y) == 0){123 ans.y = 0;124 }125 126 printf("%.10lf %.10lf %.10lf\n", ans.x, ans.y, ansp);127 }128 129 int main(){130 //freopen("data.in", "r", stdin);131 //freopen("data.out", "w", stdout);132 int t;133 cin>> t;134 while(t--){135 input();136 solve();137 }138 return 0;139 }
hdu 4998
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。