HackerRank Week of Code 23——Enclosure(等周定理+余弦定理)

Vigo the Carpathian is an evil feudal lord. He wants to seize land from his serfs by enclosing it with a polygonal fence where each respective side has a strictly specified length. Can you help him maximize the fenced area?

Given a sequence of n lengths (i.e., L1,L2,,Ln ) where each is the length of the kth side, find a sequence of points (where pk=(xk,yk) ) such that dist (pk,pk+1)=Lk and dist (p1,pn)=Ln where dist (a,b)is the Euclidean distance between points a and b. Note that the first point, p1 , must be (0,0)and the second point, p2 , must be (0,L1) . These points must correspond to the ordered clockwise vertices of the simple polygon having the maximum possible area for the given side lengths. Then print the points according to the instructions in the Output Format section below.

Input Format

The first line contains a single integer,n , denoting the number of sides in the polygon.
The second line contains n space-separated positive integers describing each respective Lk . It is guaranteed that you can form an -edge polygon with the given sequence of lengths.

Constraints

  • 3n104
  • 1LK104

Output Format

For each of the n points (i.e., vertices in the polygon), print three lines in the following format:

The first line must contain a single floating-point number denoting the point's x-coordinate.
The second line must contain a single floating-point number denoting the point's y-coordinate.
The third line must be empty and serves as a visual spacer between the last point's -coordinate and the next point's x-coordinate.

You must print a total of 3*n lines of output. Your output is considered to be correct if the absolute difference from the correct answer for each coordinate is not greater than 101 . It is guaranteed that the exact correct answer is unique.

Sample Input 0

4
1 2 1 2

Sample Output 0

0.000000
0.000000

0.000000
1.000000

2.000000
1.000000

2.000000
0.000000

Explanation 0

The enclosure is a quadrilateral (specifically, a parallellogram). The area enclosed by the fence is maximal when it’s a rectangle.

Sample Input 1

3
1 1 1

Sample Output 1

0.000000
0.000000

0.000000
1.000000

0.866025
0.500000

Explanation 1

The only possible polygon is an equilateral triangle.

按照顺时针的顺序给你n边形的边长,输出n边形的n个顶点的坐标使得多边形的面积最大。

当周长已知的时候,多边形的面积越接近圆面积越大,所以最后的多边形一定有一个外接圆,多边形的边长为圆上的弦长。所以我们根据这个条件可以求出对应的圆心角。所以我们可以根据圆心角的大小判断所选的直径是不是合适。二分出圆的直径,然后向量旋转求坐标。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double pi = acos(-1.0);
const int maxn = 1e4+100;
double a[maxn];
struct node{
    double x,y;
    node(){}
    node(double _x,double _y):x(_x),y(_y){}
    node operator + (const node &b)const  {
        return node(x+b.x,y+b.y);
    }
    node operator * (const double &b) const{ //向量旋转
        return node(x*cos(b)-y*sin(b),x*sin(b)+y*cos(b));
    }
}ans[maxn];
int main(){
    int n;
    scanf("%d",&n);
    double r = 0;
    for(int i = 0;i<n;i++) {
        scanf("%lf",&a[i]);
        r+=a[i];
    }
    int mx = 0;
    for(int i = 1;i<n;i++) if(a[i]>a[mx]) mx = i;
    double l = a[mx]/2;
    double phi = 0;
    for(int i = 0;i<n;i++) {
            if(i != mx)phi += acos(1-a[i]*a[i]/(2*l*l));
    }
    bool flag = phi<pi;
    r *=2;
    while(r-l>eps) {//二分半径
        double mid = (l+r)/2;
        double phi = 0;
        for(int i = 0;i<n;i++) if(i!=mx) phi += acos(1-a[i]*a[i]/(2*mid*mid));
        double phii = acos(1-a[mx]*a[mx]/(2*mid*mid));
        if(flag) {
            if(phi<phii) l = mid;
            else r = mid;
        }
        else {
            if(phi+phii > 2*pi) l = mid;
            else r = mid;
        }
    }
    r = l;
    ans[0].x = 0; ans[0].y = 0;
    ans[1].x = 0,ans[1].y= a[0];
    node ve,circ;
    if(flag && mx == 0) {//判断多边形在圆中的位置
        ve.x = sqrt(r*r-a[0]*a[0]/4);
        ve.y = a[0]/2;
        circ.x = -ve.x; circ.y = a[0]/2;
    }
    else {
        ve.x = -sqrt(r*r-a[0]*a[0]/4);
        ve.y = a[0]/2;
        circ.x = -ve.x; circ.y = ve.y;
    }
    for(int i = 1;i<n;i++) {
        double c = acos(1-a[i]*a[i]/(2*r*r));
        if(flag && i ==mx) c = 2*pi-c;
        c = -c;
        ve = ve*c;
        ans[i+1] = circ+ve;
    }
    for(int i = 0;i<n;i++) printf("%.6f\n%.6f\n\n",ans[i].x,ans[i].y);
    return 0;
}

你可能感兴趣的:(HackerRank Week of Code 23——Enclosure(等周定理+余弦定理))