凸包应用

http://acm.hnu.cn/online/?action=problem&type=show&id=13343


Around the Track
Time Limit: 1000ms, Special Time Limit:2500ms,Memory Limit:32768KB
Total submit users: 0, Accepted users:0
Problem 13343 : No special judgement
Problem description

In order to compare race tracks, we wish to compute their lengths. A racetrack is strictly two-dimensional (no elevation). It is described by two simple polygons, where one is completely contained inside the other. The track is the region between these two polygons. We define the length of the track as the absolute minimum distance that one needs to travel in order to complete a lap. This could involve traveling on the very edge of the track and arbitrarily sharp cornering (see Figure A.1).

Input

The input consists of: • one line with one integer n (3 ≤ n ≤ 50), the number of vertices of the inner polygon; • n lines, the ith of which contains two integers xiand yi(−5000 ≤ xi,yi≤ 5000): the coordinates of the ith vertex of the inner polygon; • one line with one integer m (3 ≤ m ≤ 50), the number of vertices of the outer polygon; • m lines, the ith of which contains two integers xiand yi(−5000 ≤ xi,yi≤ 5000): the coordinates of the ith vertex of the outer polygon. For both polygons, the vertices are given in counterclockwise order. The borders of the two polygons do not intersect or touch each other.

Output

Output one line with one floating point number: the length of the race track. Your answer should have an absolute or relative error of at most 10^(−6).

Sample Input
3
1 1
2 1
1 2
3
0 0
4 0
0 4
5
1 1
5 1
5 5
3 3
1 5
4
0 0
6 0
6 6
0 6
5
1 1
5 1
5 5
3 3
1 5
5
0 0
6 0
6 6
3 4
0 6
Sample Output
3.41421356237309
16
16.4721359549996

思路:

1,求出外圈凸包,将不在外圈凸包中的外圈上的点加入集合B.

2,求出内圈凸包.

3,逐个判断B中的点是否在内圈凸包内.

4,排序,求和。

# include <iostream>
# include <stack>
# include <string.h>
#include <math.h>
#include<algorithm>
#include<queue>
#include <stdio.h>
using namespace std;

int vis[55];
bool mark[55];
typedef struct Point{
    int x, y;
    bool operator < (const Point& other) const{
        if (y != other.y)
            return y < other.y;
        return x < other.x;
    }
}Point;
Point p[55],q[105];
Point ans[105];
int Cross(Point a,Point b,Point c){
    return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}
bool cmp(Point a,Point b){
    return Cross(p[0], a, b)>0;
}
bool _cmp(Point a,Point b){
    return Cross(q[0], a, b)>0;
}
bool __cmp(Point a,Point b){
    return Cross(ans[0], a, b)>0;
}
int main(){
    int N;
    int m,l, i, j;

    //scanf("%d", &N);
    while (scanf("%d", &l)!=EOF){
        //ÊäÈëÄÚȦ  ----------q
        for(i=0;i<l;i++)   scanf("%d%d",&q[i].x,&q[i].y);
       //ÊäÈëÍâȦ   ----------p
        scanf("%d",&m);
        for (i = 0; i < m; i++)  scanf("%d%d",&p[i].x,&p[i].y);
        sort(p, p + m);
        sort(p, p + m, cmp);
        vis[0] = 0;vis[1] = 1;
        ans[0] = p[0]; ans[1] = p[1];
        for (j = i = 2; i < m; i++){
            while (j>1&&Cross(ans[j - 1], ans[j - 2], p[i])>0)
                    j--;
            vis[j]=i;
            ans[j++] = p[i];
        }
        memset(mark,0,sizeof(mark));
        for(i=0;i<j;i++) mark[vis[i]]=1;

        sort(q, q + l);  sort(q, q + l, _cmp);
        ans[0] = q[0];  ans[1] = q[1];

        for (j = i = 2; i < l; i++){
            while (j>1&&Cross(ans[j - 1], ans[j - 2], q[i])>0)
                    j--;
            //vis[j]=i;
            ans[j] = q[i];
            j++;
        } //for
        sort(ans, ans + j);
        sort(ans, ans + j, __cmp);
        int k,t=j;
        int pos[55];
        for(i=0;i<m;i++) if(!mark[i]){
            for(k=0;k<j;k++)
                if(Cross(ans[k],ans[k-1],p[i])<0)
                    {ans[t++]=p[i];}
        }
        sort(ans, ans + t);
        sort(ans, ans + t, __cmp);
        double sum=0;
        for (i = 0; i < t; i++) {
            sum+=sqrt((ans[i].x-ans[(i+1)%t].x)*(ans[i].x-ans[(i+1)%t].x)+(ans[i].y-ans[(i+1)%t].y)*(ans[i].y-ans[(i+1)%t].y));
        }
        printf("%lf\n",sum);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值