题目链接: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");
}
}
}
京公网安备 11010502036488号