United Kingdom and Ireland Programming Contest 2017 B

codeforces.com/gym/222400
题意是有一个饼干,这个饼干是标准的一个多边形,然后给这个饼干上的顶点,然后问要是将他放入一个杯子中的话,这个杯子的最小直径是多少?

一开始的第一反应是两点之间的最远距离,但是TD说了可以将饼干竖起来之后的想法,就想到了旋转卡壳算法,然而并不知道旋转卡壳是干什么的,计算几何这块太差了。一定赶紧补起来。
那就先拿今天的这几个题来练一练。

因为可以竖起来 举个离子。
4
0 0
5 0
5 2
0 2

给定这四个点,显然这是一个长方形,按我的思路应该是对角线,但是这个是 2 ,及最短边。

那样的话这个题就是找两条平行线,这两条平行线恰好过多边形其中的两个顶点,并且这两条平行线之间的距离还是所有平行线中最小的。
等价于选择一对距离最小的平行线夹住所有点。枚举一条边,计算两侧所有点到这条直线的距离的最大值即可。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=111;
struct P{
    int x,y;
    P(){}
    P(int _x,int _y){x=_x,y=_y;}
    P operator-(P b){return P(x-b.x,y-b.y);} // 向量减 重载操作符。
    double len(){return hypot(x,y);} // 以 x,y 为直角边直角三角形的斜边长。
}a[N];

int n,i,j,k;

double cross(P a,P b){return a.x*b.y-a.y*b.x;} // 叉积
double dist(P p,P a,P b){ // 以向量ab为方向的过p的平行线。但是有正负之分。
    return cross(p-a,b-a)/(b-a).len();  // 叉积 / 其中一边的边长
} // 这个写法真的服 ORZ 帅气
int main(){
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    double ans=1e100;
    a[n+1]=a[1];
    for(i=1;i<=n;i++)
    for(j=1;j<i;j++)
    {
        double l=1e100,r=-1e100;
        for(k=1;k<=n;k++)
        {
            l=min(l,dist(a[k],a[i],a[j])); // 在a[i]a[j]右面的是负数
            r=max(r,dist(a[k],a[i],a[j])); // 在a[i]a[j]左面的是正数
        }
        r-=l;//平行线之间的长度
        ans=min(ans,r);
    }
    printf("%.10f",ans);
}

转自
https://www.cnblogs.com/clrs97/p/7768748.html

总结一下就是这个题目学到了用叉积求某一方向平行线。以及叉积的正负和方向。

猜你喜欢

转载自blog.csdn.net/AC_jie/article/details/79839344
今日推荐