问题虫洞:B - Rolling The Polygon Gym - 102222B
黑洞内窥:
给你一个n边的凸多边形,给你这个多边形所有顶点的坐标。
(逆顺序给出所有顶点)然后再给你多边形内或边界上一个点的坐标,
接着按边滚动这个多边形一周,需要我们计算出目标点移动轨迹的长度。
思维光年:
天马行空:
求出凸多边形的每条边按顺时针转到x轴的角度,
再求出凸多边形的每个顶点到目标点的距离。
用角度差乘以距离再求和就是答案了。。
But,敲起来太难了,,,而且有些边可能转过了超过2*pi的角度。。。
理性的求解:
对于半径,首先确定圆心即使滚动角的顶点
(滚动角就是Pi、Pi+1和Pi+2所形成的夹角,那么滚动角顶点则是P1),
而目标点则是圆边上的一点,那么半径= 滚动角顶点(v[i+1])到目标点(tv)的距离
。旋转角度= 180°-滚动角° = π-acos((a*a+b*b-c*c)/(2*a*b)) ,
(注:Pi和Pi+1之间边a,Pi+1和Pi+2之间边b,Pi和Pi+2之间边c);
最后求弧长 = 半径 * 旋转角度即可。
参考博客:2018NingXia-B. Rolling The Polygon
ACcode:
#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 10025
#define INF 0x3f3f3f3f//将近int类型最大数的一半,而且乘2不会爆int
#define MOD 1000000007 // MOD%4 = 3
const double pi = acos(-1.0);
const double eps = 1e-6;
struct point
{
int x, y;
} p[55];
double jvli(point p1, point p2)
{
return sqrt(abs((p1.x-p2.x)*(p1.x-p2.x))+abs((p1.y-p2.y)*(p1.y-p2.y)));
}
int main()
{
int t, aaa=1;
cin >> t;
while(t--)
{
int n;
scanf("%d", &n);
point q;
double ans = 0.0;
for(int i=0; i<n; ++i)
scanf("%d %d", &p[i].x, &p[i].y);
scanf("%d %d", &q.x, &q.y);
p[n] = p[0];
p[n+1] = p[1];
for(int i=0; i<n; ++i)
{
double a, b, c;
a = jvli(p[i], p[i+1]);
b = jvli(p[i+1], p[i+2]);
c = jvli(p[i+2], p[i]);
double r = jvli(p[i+1], q);
double Angle = pi - acos((a*a+b*b-c*c)/(2*a*b));
ans += (r*Angle);
}
printf("Case #%d: %.3f\n", aaa++, ans);
}
return 0;
}