Rolling The Polygon

xiaoxiao2021-03-01  24

Bahiyyah has a convex polygon with nn vertices P_0, P_1, \cdots, P_{n-1}P0​,P1​,⋯,Pn−1​ in the counterclockwise order.Two vertices with consecutive indexes are adjacent, and besides, P_0P0​ and P_{n-1}Pn−1​ are adjacent.She also assigns a point QQ inside the polygon which may appear on the border.

Now, Bahiyyah decides to roll the polygon along a straight line and calculate the length of the trajectory (or track) of point QQ.

To help clarify, we suppose P_n = P_0, P_{n+1} = P_1Pn​=P0​,Pn+1​=P1​ and assume the edge between P_0P0​ and P_1P1​ is lying on the line at first.At that point when the edge between P_{i-1}Pi−1​ and P_iPi​ lies on the line, Bahiyyah rolls the polygon forward rotating the polygon along the vertex P_iPi​ until the next edge (which is between P_iPi​ and P_{i+1}Pi+1​) meets the line.She will stop the rolling when the edge between P_nPn​ and P_{n+1}Pn+1​ (which is same as the edge between P_0P0​ and P_1P1​) meets the line again.

Input Format

The input contains several test cases, and the first line is a positive integer TT indicating the number of test cases which is up to 5050.

For each test case, the first line contains an integer n~(3\le n \le 50)n (3≤n≤50) indicating the number of vertices of the given convex polygon.Following nn lines describe vertices of the polygon in the counterclockwise order.The ii-th line of them contains two integers x_{i-1}xi−1​ and y_{i-1}yi−1​, which are the coordinates of point P_{i-1}Pi−1​.The last line contains two integers x_QxQ​ and y_QyQ​, which are the coordinates of point QQ.

We guarantee that all coordinates are in the range of -10^3−103 to 10^3103, and point QQ is located inside the polygon or lies on its border.

Output Format

For each test case, output a line containing Case \#x: y, where xx is the test case number starting from 11, and yyis the length of the trajectory of the point QQ rounded to 33 places.We guarantee that 44-th place after the decimal point in the precise answer would not be 44 or 55.

Hint

The following figure is the the trajectory of the point QQ in the first sample test case.

4 4 0 0 2 0 2 2 0 2 1 1 3 0 0 2 1 1 2 1 1 5 0 0 1 0 2 2 1 3 -1 2 0 0 6 0 0 3 0 4 1 2 2 1 2 -1 1 1 0

Case #1: 8.886 Case #2: 7.318 Case #3: 12.102 Case #4: 14.537

按照逆时针绕向给出一个凸多边形的 n 个顶点 P0,P1,··· ,Pn−1，再给出凸多边形内部（含边界） 一点 Q。现在要将这个凸多边形在地上无滑动地滚动一周，初始时 P0P1 边与地面接触，假设当前是 PiP(i+1) mod n 边与地面接触，那么滚动一下之后则是 P(i+1) mod nP(i+2) mod n 边与地面接触。不难发现， 从初始状态滚动 n 下之后 P0P1 边再一次与地面接触，这时认为凸多边形已经滚动了一周。现在你需要 求出凸多边形滚动一周之后点 Q 经过的轨迹长度。 输入格式 第一行包含一个整数 T，表示测试数据的组数。       接下来依次描述 T 组测试数据。对于每组测试数据：       第一行包含一个整数 n，表示凸多边形的顶点数。 接下来 n 行，每行包含两个整数 xPi,yPi，按照逆时针的顺序给出凸多边形 n 个顶点 P1,P2,··· ,Pn 的坐标。       最后一行包含两个整数 xQ,yQ，表示点 Q 的坐标。       保证点 Q 在凸多边形内部（含边界）。       输出一行信息 "Case #x: y"（不含引号），其中 x 表示这是第 x 组测试数据， y 表示凸多边形滚动一周之后点 Q 经过的轨迹长度，四舍五入精确到小数点后 3 位，数据保证答案的小 数点后第 4 位不是 4 或 5。

#include<stdio.h> #include<math.h> using namespace std; int t,n;//样例数，端点数； int x[55],y[55],xx,yy;//端点坐标,Q点坐标 double angle[55],dis[55];//旋转角的角度（弧度），Q点到各个点的距离； double dist(int a,int b) {     return sqrt((a-xx)*(a-xx)+(b-yy)*(b-yy)); } double dist2(int a,int b,int c,int d) {     return sqrt((a-c)*(a-c)+(b-d)*(b-d)); } int main() {     scanf("%d",&t);     int casee=0,i;     double t1,t2,t3,ans;     while(t--)     {         scanf("%d",&n);         for(i=1;i<=n;i++)             scanf("%d %d",&x[i],&y[i]);         scanf("%d %d",&xx,&yy);         for(i=1;i<=n;i++)             dis[i]=dist(x[i],y[i]);         for(i=1;i<=n;i++)         {             if(i==1)                {                    t1=dist2(x[1],y[1],x[n],y[n]);                    t2=dist2(x[1],y[1],x[2],y[2]);                    t3=dist2(x[2],y[2],x[n],y[n]);                }             else if(i==n)                {                    t1=dist2(x[n],y[n],x[1],y[1]);                    t2=dist2(x[n],y[n],x[n-1],y[n-1]);                    t3=dist2(x[1],y[1],x[n-1],y[n-1]);                }             else                {                    t1=dist2(x[i],y[i],x[i-1],y[i-1]);                    t2=dist2(x[i],y[i],x[i+1],y[i+1]);                    t3=dist2(x[i-1],y[i-1],x[i+1],y[i+1]);                }                angle[i]=acos((t1*t1+t2*t2-t3*t3)/(2*t1*t2));         }         ans=0;         for(i=1;i<=n;i++)             ans+=dis[i]*(acos(-1.0)-angle[i]);//圆弧长度 弧度*半径         printf("Case #%d: %.3lf\n",++casee,ans);     }     return 0; }