Ural-1020. Rope(简单计算几何)

1020. Rope

Time limit: 1.0 second
Memory limit: 64 MB
Plotters have barbarously hammered N nails into an innocent plane shape, so that one can see now only heads. Moreover, pursuing their mean object, they have hammered all the nails into the vertices of a convex polygon. After that they…it is awful… have roped off the nails, so that the shape felt upset (the rope was very thin). They’ve done it as it is shown in the figure.
Problem illustration
Your task is to find out a length of the rope.

Input

There two numbers in the first line of the standard input: N — a number of nails (1 ≤ N ≤ 100), and a real number R — a radius of heads of nails. All the heads have the same radius. Further there are N lines, each of them contains a pair of real coordinates (separated by a space) of centers of nails. An absolute value of the coordinates doesn’t exceed 100. The nails are described either in a clockwise or in a counterclockwise order starting from an arbitrary nail. Heads of different nails don’t overlap.

Output

Output a real number with two digits precision (after a decimal point) — a length of the rope.

Sample

input output
4 1
0.0 0.0
2.0 0.0
2.0 2.0
0.0 2.0
14.28


题意: Plotters 向平面上钉钉子,共有n个钉子,每个钉子的上端都可视为一个圆,半径为r,所有的钉子型号都一样,最后用绳子将所有的钉子包围,行程一个凸多边形,求绳子的最短长度。

思路:
当n=1时,长度为圆的周长
当n=2时,长度为2*圆心距+一个圆的周长
当n>2时,长度为n个圆心所围成的凸多边形的周长+1个圆的周长
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 110;
const double eps = 1e-8;
const double PI = 3.1415926535898;
struct point
{
    double x,y;
}s[N],t[N];
bool isZero(double x)
{
    return (x>0?x:-x)<eps;
}
double dis(point a,point b)//两点间的距离
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
//向量ab和向量ac的叉积
double crossProd(point a,point b,point c)
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
//以最左下的点为基准点,其他各点(逆时针方向)以极角从小到大的排序规则
int cmp(const void * a,const void * b)
{
    point *c = (point *)a;
    point *d = (point *)b;
    double k = crossProd(t[0],*c,*d);
    if(k<eps||(isZero(k) && (dis(t[0],*c)>dis(t[0],*d))))
        return 1;
    return -1;
}
double Graham(int n) {
    double x = t[0].x;
    double y = t[0].y;
    int k = 0;
    for (int i=1; i<n; ++i)
    {//找到最左下的一个点
        if (t[i].x<x || (t[i].x==x && t[i].y<y)) {
            x = t[i].x;
            y = t[i].y;
            k = i;
        }
    }
    //交换,将最左的点移至数组首位
    point tmp = t[k];
    t[k] = t[0];
    t[0] = tmp;
    qsort(t+1, n-1, sizeof(point), cmp);
//    sort(t+1,n-1,cmp);
    t[n] = t[0];
    s[0] = t[0];
    s[1] = t[1];
    s[2] = t[2];
    int top = 2;
    for (int i=3; i<=n; ++i)
    {//加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点
        while (crossProd(s[top-1], s[top], t[i])<=eps && top>=2) --top;
        s[++top] = t[i];//在当前情况下符合凸包的点,入栈
    }
    double len = 0;
    for (int i=0; i<top; ++i) len += dis(s[i], s[i+1]);
    return len;
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n;
    double r;
    scanf("%d%lf",&n,&r);
    for(int i=0;i<n;i++)
    {
        scanf("%lf%lf",&t[i].x,&t[i].y);
    }
    if(n==1)
    {
        printf("%.2lf\n",2*PI*r);
    }
    else if(n==2)
    {
        printf("%.2lf\n",2*(PI*r+dis(t[0],t[1])));
    }
    else
    {
        printf("%.2lf\n",Graham(n)+2*PI*r);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值