题目链接:https://ac.nowcoder.com/acm/contest/5668/C
简要题意:
下图为某机器人右手手印的形状,左手为右手的对称图形,现在给你一个机器人的手印(可能经过平移和旋转),请判断是左手还是右手(保证一定是其中一只手)
给你20个点,按照顺时针方向或者逆时针方向给出,如下图(该图为右掌)
解题思路:
计算几何顺/逆时钟判断,(与给出三角形三个顶点求面积就差个绝对值),判断出给的点是按照顺/逆时针方向给的就可以通过边来判断左手还是右手了。
代码实现上这道题eps需要给大点,不需要那么精确。
证明:
https://www.zybang.com/question/761f8b42a12a5b3947f165e685fd89fd.html
总结出来的计算技巧(交叉相乘,注意正负号):
代码:
#include<bits/stdc++.h> using namespace std; #define eps 1e-1 struct point{ double x, y; }s[30]; double dis(point a, point b) { return 1.0 * sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double axb(point A, point B, point C) { return A.x*B.y-B.x*A.y+B.x*C.y-C.x*B.y+C.x*A.y-A.x*C.y; } int main() { int t; scanf("%d",&t); while(t--) { for(int i = 1; i <= 20; i++) { scanf("%lf%lf",&s[i].x,&s[i].y); s[i + 20] = s[i]; //一圈 } int q1, q2, q3; for(int i = 1; i <= 20; i++) { if(fabs(dis(s[i], s[i+1]) - 9.0) < eps) { q1 = i; q2 = i + 1; q3 = i + 2; break; } } bool flag; // 左1右0 if(axb(s[q1],s[q2],s[q3]) < 0.0) //顺时针 { for(int i = 1; i <= 20; i++) { double dis1 = dis(s[i],s[i+1]); if(fabs(dis1 - 9.0) < eps) { double dis2 = dis(s[i+1], s[i+2]); if(fabs(dis2 - 8.0) < eps) flag = 1; else flag = 0; break; } } } else //逆时针 { for(int i = 1; i <= 20; i++) { double dis1 = dis(s[i],s[i+1]); if(fabs(dis1 - 9.0) < eps) { double dis2 = dis(s[i+1], s[i+2]); if(fabs(dis2 - 8.0) < eps) flag = 0; else flag = 1; break; } } } if(flag) { printf("left\n"); } else { printf("right\n"); } } }