Codeforces Gym - 101635K Blowing Candles [旋转卡壳]

题意:给你平面上一些点,求一个凸包的最短直径

思路:旋转卡壳,然后搞一下就行了可旋转卡壳求最远点差不多,cur带表的是求出的对锺点,然后与当前的直线p[i],p[i+1],求一下距离

代码:

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-16;
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct point
{
    double x,y;
    point(int _x = 0,int _y = 0)
    {
        x = _x;
        y = _y;
    }
    point operator -(const point &b)const
    {
        return point(x - b.x, y - b.y);
    }
    double operator ^(const point &b)const
    {
        return x*b.y - y*b.x;
    }
    double operator *(const point &b)const
    {
        return x*b.x + y*b.y;
    }
    void sc()
    {
        scanf("%lf%lf",&x,&y);
    }
};

struct Line
{
    point s,e;
    Line() {}
    Line(point _s,point _e)
    {
        s = _s;
        e = _e;
    }
    pair<int,point> operator &(const Line &b)const
    {
        point res = s;
        if(sgn((s-e)^(b.s-b.e)) == 0)
        {
            if(sgn((s-b.e)^(b.s-b.e)) == 0)
                return make_pair(0,res);
            else return make_pair(1,res);
        }
        double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x += (e.x-s.x)*t;
        res.y += (e.y-s.y)*t;
        return make_pair(2,res);
    }
};
double dist(point a,point b)
{
    return (double)sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
point NearestpointToLineSeg(point P,Line L)
{
    point result;
    double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
    if(t >= 0.000 && t <= 1.0000)
    {
        result.x = L.s.x + (L.e.x - L.s.x)*t;
        result.y = L.s.y + (L.e.y - L.s.y)*t;
    }
    else
    {
        if(dist(P,L.s) < dist(P,L.e))
            result = L.s;
        else result = L.e;
    }
    return result;
}
double emmm(point P,Line L)
{
    point zz=NearestpointToLineSeg(P,L);
    return dist(zz,P);
}
const int MAXN = 2e5+7;
point List[MAXN];
int Stack[MAXN],top;
bool _cmp(point p1,point p2)
{
    double tmp = (p1-List[0])^(p2-List[0]);
    if(tmp > 0)return true;
    else if(tmp == 0 && dist(p1,List[0]) <= dist(p2,List[0]))
        return true;
    else return false;
}
void Graham(int n)
{
    point p0;
    int k = 0;
    p0 = List[0];
    for(int i = 1; i < n; i++){
        if(p0.y > List[i].y || (p0.y == List[i].y && p0.x > List[i].x))
        {
            p0 = List[i];
            k = i;
        }
    }
    swap(List[k],List[0]);
    sort(List+1,List+n,_cmp);
    if(n == 1)
    {
        top = 1;
        Stack[0] = 0;
        return;
    }
    if(n == 2)
    {
        top = 2;
        Stack[0] = 0;
        Stack[1] = 1;
        return;
    }
    Stack[0] = 0;
    Stack[1] = 1;
    top = 2;
    for(int i = 2; i < n; i++)
    {
        while(top > 1 &&
                ((List[Stack[top-1]]-List[Stack[top-2]])^(List[i]-List[Stack[top-2]])) <= 0)
            top--;
        Stack[top++] = i;
    }
}
double rotating_calipers(point p[],int n)
{
    double ans = 999999999999999999999.0;
    point v;
    int cur = 1;
    for(int i = 0; i < n; i++)
    {
        v = p[i]-p[(i+1)%n];
        while((v^(p[(cur+1)%n]-p[cur])) < 0){
            cur = (cur+1)%n;s
        }
        Line qw=Line(p[(i)%n],p[(i+1)%n]);
//        point zz=NearestpointToLineSeg(p[cur],qw);
        double as=emmm(p[cur],qw);
        //as=max(as,zx);
        ans=min(ans,as);
//        ans=min(ans,max(dist(p[i],p[cur]),dist(p[(i+1)%n],p[(cur+1)%n])));
    }
    return ans;
}
point p[MAXN];
int main()
{
    int n,r;
    while(~scanf("%d%d",&n,&r))
    {

        for(int i = 0; i < n; i++)List[i].sc();
        Graham(n);
        for(int i = 0; i < top; i++)p[i] = List[Stack[i]];
        printf("%.16f\n",rotating_calipers(p,top));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lalalatianlalu/p/8973980.html

时间: 2024-08-12 04:37:02

Codeforces Gym - 101635K Blowing Candles [旋转卡壳]的相关文章

Gym - 101635K:Blowing Candles (简单旋转卡壳,求凸包宽度)

题意:给定N个点,用矩形将所有点覆盖,要求矩形宽度最小. 思路:裸体,旋转卡壳去rotate即可. 最远距离是点到点:宽度是点到边. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define RC rotating_calipers using namespace std; const int maxn=400010; struct point{ ll x,y

【模拟】ECNA 2015 I What&#39;s on the Grille? (Codeforces GYM 100825)

题目链接: http://codeforces.com/gym/100825 题目大意: 栅栏密码.给定N(N<=10),密钥为一个N*N的矩阵,'.'代表空格可以看到,'X'代表被遮挡,还有密文字符串S,长度为N*N 每次将这个矩阵顺时针旋转90°,把矩阵中空格对应的位置按照从上到下从左到右的顺序依次填充上密文字符,求最终这个密文字符能否填满N*N的矩阵,能按顺序输出得到的答案,不能输出"invalid grille" 题目思路: [模拟] 直接模拟即可.旋转的坐标公式很好推.

BZOJ 1185 HNOI 2007 最小矩形覆盖 旋转卡壳

题目大意:给出平面上的一些点,问面积最小的矩形满足覆盖所有的点. 思路:覆盖问题和不是凸包上的点没关系,先做凸包.根据贪心的思想,这个覆盖了所有点的矩形肯定至少有一条边与凸包上的边重合,那么我们枚举凸包上的每一条边,对于这个已经确定了一条边的矩形,不难确定其他三个边.注意到已知当前直线的向量,就可以求出两侧和对面的向量,而这三个向量随着枚举的边的移动是单调的,所以就可以用旋转卡壳来卡住剩下的三条边. 但是旋转卡壳时的初值会出问题,如果按照逆时针的顺序求出剩下的三条边的时候,要想通过向量直接卡第三

NYOJ_253:LK的旅行(旋转卡壳入门)

题目链接 求平面最大点对. 找凸包 -> 根据凸包运用旋转卡壳算法求最大点对(套用kuang巨模板) 关于旋转卡壳算法 #include<bits/stdc++.h> using namespace std; struct point { int x,y; point operator -(const point& rhs)const { point ret; ret.x=x-rhs.x; ret.y=y-rhs.y; return ret; } int operator *(c

POJ 2079 Triangle [旋转卡壳]

Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 9525   Accepted: 2845 Description Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices are from the given points. Input

【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle

[最小矩形面积覆盖:凸包+旋转卡壳]UVA 10173 Smallest Bounding Rectangle 题目链接:UVA 10173 Smallest Bounding Rectangle 题目大意 给你n个点,求能够覆盖所有点集的最小矩形面积. 笔者的第2道凸包题目,凸包 + 旋转卡壳,实现点集的最小矩形面积覆盖问题 ">=0"写成"<=0"坑了我一下午!QAQ 说一下思路 ①Graham's Scan法构建凸包,时间复杂度O(nlogn) ②

Codeforces gym Hello 2015 Div1 B and Div2 D

Codeforces gym 100571 problem D Problem 给一个有向图G<V,E>和源点S,边的属性有长度L和颜色C,即E=<L,C>.进行Q次询问,每次给定一个点X,输出S到X的最短路的长度(不存在则输出 -1).但要求S到X的路径中相邻两条边颜色不一样. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 |V|, |E|: [1, 10^5] X, S: [1, |V| ] L: [1, 10^9] |C|

【旋转卡壳】poj3608 Bridge Across Islands

给你俩凸包,问你它们的最短距离. 咋做就不讲了,经典题,网上一片题解. 把凸包上的点逆时针排序.可以取它们的平均点,然后作极角排序. 旋转卡壳其实是个很模板化的东西-- 先初始化分别在凸包P和Q上取哪个点,一般在P上取纵坐标最小的点,在Q上取纵坐标最大的点 for i=1 to n(n是凸包P上的点数) { while(两条边的叉积>0) { 凸包Q上的点++ } 计算当前两条边之间的答案(或者说每条边的2个端点到另一条边的答案) 凸包P上的点++ } #include<cstdio>

HDU 5251 矩形面积(二维凸包旋转卡壳最小矩形覆盖问题) --2015百度之星题目

B - 矩形面积 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少. Input 第一行一个正整数 T,代表测试数据组数(),接下来 T 组测试数据. 每组测试数据占若干行,第一行一个正整数 ,代表矩形的数量.接下来 N 行,每行 8