题面:
-
总Time Limit:
- 1000ms Memory Limit:
- 65536kB
-
Description
-
Consider a transformation T, which transforms each point (x, y) to (x cos y, x sin y) (0 ≤ x ≤ 1000, 0 ≤ y < 2π). Given a simple polygon P, you need to calculate the area of T(P).
There are two pictures shown below. The left picture shows the simple polygon P given by the sample input, and the one on the right shows the image of T(P).
Input
-
The first line contains an integer, indicates the number of test cases, which is no more than 30.
The first line of each test case contains a positive integer N (3 ≤ N ≤ 100000), indicates the number of vertices in P. Then N lines follow. Each line contains two real numbers X and Y, giving the coordinate of a vertex. The vertices will be given in either clockwise or counterclockwise order.
Output
- For each test case, output the answer in a single line. Your answer will be judged correct if its relative number is no more than 0.000001. Sample Input
-
1 6 2 5.026548246 5 2.513274123 7 5.026548246 9 5.654866776 7 1.256637061 2 0.628318531
Sample Output
-
90.16370917
看上去是个水题,貌似主要不是靠算法而是微积分……
题目大意:给出一个n边形,将该n边形上的每个点(x,y)都转换为(xcosy,xsiny),得到一个新的图形,求新图形的面积。
知道多边形上顶点的坐标,求该多边形的面积时,只需要依次遍历多边形的边,求原点(或其他任意的固定点)到多边形边的两个端点的两个向量的叉积之和
然后把所有叉积之和加起来取绝对值,乘1/2就得到多边形的面积,该方法适用于任意简单多边形
看题面脑补一下,这题把每个(x,y)坐标都转换为(xcosy,xsiny),得到的图形应该是是由弧而不是直线围成的。但是,直接求每条弧的方程很难,就算能求方程,想用弧的方程求图形的面积貌似更难。继续脑补,求这个由圆弧围成的图形的面积可以用类似于求任意多边形面积的方法。
这样,先求任意一段圆弧对应的面积(或者说是圆弧上的点到原点距离的积分)。上图:
图中AB代表多边形P上任意一条线段 M为AB上一点 弧A'B'为AB对应的T(P)上的弧,M'为M进行转换后的位置
设A(x1,y1), B(x2, y2), M(x,y) 可以求出直线AB的方程,也就是x和y的关系:
x(y)=x1+(y1-y2)*(y-y1)/(x1-x2)
x的绝对值就是M’到原点的距离,y的值表示M'O与直线Ox的夹角(旋转角)
这里就得到了M‘到原点的距离与点M'旋转角的关系,可以通过积分求出由弧A'B', 线段A'O, 线段B'O围成的面积大小:
如果向同一个方向积分,得到的就是整个图形T(P)的面积。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <string>
using namespace std;
#define PI acos(-1.0)
const int INF = 0x7fffffff;
const double eps = 1e-10;
double x[100000 + 10], y[100000 + 10];
int main() {
int _;
cin>>_;
while(_--){
int n;
cin>>n;
for(int i=0;i<n;i++){
scanf("%lf %lf", &x[i], &y[i]);
}
int i,j;
double S = 0.0;
for(i=0;i<n;i++){
j=(i+1)%n;
double x1=x[i],y1=y[i];
double x2=x[j],y2=y[j];
if(fabs(y1 - y2) < eps)continue;
double A = (x1-x2)/(y1-y2);
double B = ((x2-x1)*y1/(y1-y2)) + x1;
double a,b,c;
a=A*A/3;
b=A*B;
c=B*B;
double s1 = a*(y1*y1*y1) + b*(y1*y1) + c*(y1);
double s2 = a*(y2*y2*y2) + b*(y2*y2) + c*(y2);
S += (s1-s2);
}
printf("%.8lf\n",fabs(S)/2);
}
}
这次北大校赛全程高能,被踩得很爽……人生圆满即视感