POJ 1113 二维凸包

题意:国王把自己城堡看成了一个点,让你找一个凸包把所有的城堡包住并且这个凸包距离城堡最近不能小于L,求这个凸包的最短长度。

题意就是求凸包最短长度再加上以L为半径的圆的周长就有解了。是一道使用Graham扫描法的模板题。一开始我用STL里的stack建栈,c++超时,g++985ms,而且感觉不是那么方便。之后我又用数组建栈写了,果断0ms,并且代码也没有那么长。

这个数组建栈的

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double PointType;
struct point
{
    PointType x,y;
};
point data[1005],stack[1005],MinA;
int top;
PointType Direction(point pi,point pj,point pk) //判断向量PiPj在向量PiPk的顺逆时针方向 +顺-逆0共线
{
    return (pj.x-pi.x)*(pk.y-pi.y)-(pk.x-pi.x)*(pj.y-pi.y);
}
PointType Dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b)
{
    PointType k=Direction(MinA,a,b);
    if(k>0) return 1;
    if(k<0) return 0;
    return Dis(MinA,a)>Dis(MinA,b);
}
void Graham_Scan(point *a,int numa)
{
    for(int i=0; i<numa; i++)
        if(a[i].y<a[0].y||(a[i].y==a[0].y&&a[i].x<a[0].x))
            swap(a[i],a[0]);
    MinA=a[0],top=0;
    sort(a+1,a+numa,cmp);
    stack[top++]=a[0],stack[top++]=a[1],stack[top++]=a[2];
    for(int i=3; i<numa; i++)
    {
        while(Direction(stack[top-2],stack[top-1],a[i])<0)
            top--;
        stack[top++]=a[i];
    }
}
int main()
{
    int n;
    double r,pi=3.141592654;
    while(~scanf("%d%lf",&n,&r))
    {
        double sum=0;
        for(int i=0; i<n; i++)
            scanf("%lf%lf",&data[i].x,&data[i].y);
        Graham_Scan(data,n);
        for(int i=1; i<top; i++)
            sum+=Dis(stack[i],stack[i-1]);
        sum+=Dis(stack[0],stack[top-1]);
        sum+=pi*r*2;
        printf("%.0f\n",sum);
    }
    return 0;
}

这个是用STL的stack栈写的。。

#include <iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double PointType;
struct point
{
    PointType x,y;
    int num;
};
point MinA;
point Next_To_Point(stack<point> temp)
{
    point first,second;
    first=temp.top();
    temp.pop();
    second=temp.top();
    temp.push(first);
    return second;
}
PointType Direction(point pi,point pj,point pk) //判断向量PiPj在向量PiPk的顺逆时针方向 +顺-逆0共线
{
    return (pj.x-pi.x)*(pk.y-pi.y)-(pk.x-pi.x)*(pj.y-pi.y);
}
PointType Dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b)
{
    PointType k=Direction(MinA,a,b);
    if(k>0) return 1;
    if(k<0) return 0;
    return Dis(MinA,a)>Dis(MinA,b);
}
stack<point> Graham_Scan(point *a,int numa)
{
    stack<point> s;
    for(int i=0; i<numa; i++)
        if(a[i].y<a[0].y||(a[i].y==a[0].y&&a[i].x<a[0].x))
            swap(a[i],a[0]);
    MinA=a[0];
    sort(a+1,a+numa,cmp);
    s.push(a[0]),s.push(a[1]),s.push(a[2]);
    for(int i=3; i<numa; i++)
    {
        while(Direction(Next_To_Point(s),s.top(),a[i])<0&&!s.empty())
            s.pop();
        s.push(a[i]);
    }
    return s;
}
point data[1005],st[1005];
int main()
{
    int n;double r,pi=3.141592654;stack<point> ans;
    while(~scanf("%d%lf",&n,&r))
    {
        double sum=0;int w=0;
        for(int i=0;i<n;i++)
        scanf("%lf%lf",&data[i].x,&data[i].y);
        ans=Graham_Scan(data,n);
        while(!ans.empty())
            st[w++]=ans.top(),ans.pop();
        for(int i=1;i<w;i++)
            sum+=Dis(st[i],st[i-1]);
        sum+=Dis(st[0],st[w-1]);
        sum+=pi*r*2;
        printf("%.0f\n",sum);
    }
    return 0;
}
时间: 2025-01-31 01:33:00

POJ 1113 二维凸包的相关文章

GiftWrapping算法解决二维凸包问题

一.问题描述         凸集(Convex Set): 任意两点的连线都在这个集合内的集合就是一个凸集.             ⒈对于一个集合D,D中任意有限个点的线性组合的全体称为D的凸包.             ⒉对于一个集合D,所有包含D的凸集之交称为D的凸包(由此定义可以想到分治算法).         可以证明,上述两种定义是等价的.点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.下图中由红色线段表示的多边形就是点集Q={p

poj 1948 Triangular Pastures(二维0/1背包)

点击打开链接poj 1948 思路: 二维0/1背包 分析: 1 题目要求从n个木棒里面选出m个组成一个三角形,使得三角形的面积最大 2 对于三角形来说知道了两条边和周长就可以求面积,按照0/1背包的思想dp[i][j][k]表示前i个木棒能否组成第一条边为长度j,第二条长度为k.如果dp[j-v[i]][k] 或dp[j][k-v[i]] 为true则dp[j][k]就为true 3 我们求出了所有可能的组合之和,就去枚举所有的边长的情况,然后求最大的面积 代码: #include<cmath

算法:poj 1976 A Mini Locomotive (dp 二维01背包)

题目大意: 某个车站有N个火车车厢,编号为1-N,每个车厢上有xi个人. 这个车站还有 三个火车头,他们能拉最多m个车厢(m<=N/3),而且这m个车厢的编号要连续的.问这三个火车头最多 能拉多少个人. 思路: 因为m<=N/3, 所以按照贪心的思想,为了拉更多的人,每个火车 头一定是要拉m个连续的车厢. 然后,为了求某段连续的车厢共有多少人,可以前缀和预处理, 某 一段和=sum[ i ] - sum[ i-m]. f[i][j] 代表前i个车厢,用j个火车头拉,最多能拉多少人. 对于第i个

算法:poj 1948 Triangular Pastures (dp 二维01背包)

题目大意: 给N条边,把这些边组成一个三角形,问面积最大是多少?必须把所有边都用上. 思路: 对于已知周长的三角形,我们只要知道两条边的长度变可推出第三条边,所以可以得 到状态方程: f[i][j][k] 表示用前i条边,能否组成长度为j和k的两条边 初始化f[0][0][0] = true: f[i][j][k] = f[i-1][j-len[i]][k] || f[i-1][j][k-len[i]]; 如果f[i][j][k]=true ,那么就计算以j,k,sum-j-k为三条边能否组成三

ps怎么把二维码设置为透明背景?

  ps怎么把二维码设置为透明背景?微信二维码在下载之后的图片是带有一个白色背景的,我们在设计图稿时,二维码带有一个白色背景非常的不方便,我们应该怎么把白色的背景去掉呢?下面我用ps简单介绍一下去掉二维码白色背景的方法. 1.首先打开photosop,新建一个透明图层,文件>新建,新建时,背景色选择透明色. 2.在这个文档中打开我们要变为透明背景的二维码,打开之后如下图所示.(二维码为自己生成,不存在广告信息) 3.然后在右侧选择图层样板,选择图层旁边的通道. 4.通道种我们会看到有rgb 红

微信扫描二维码登录网站代码

 用户通过扫描网页提供的二维码实现登陆信息获取,大家参考使用吧 请先下载  snoopy 类   代码如下: <?php /**  *  微信公众平台PHP-SDK  *  Wechatauth为非官方微信登陆API  *  用户通过扫描网页提供的二维码实现登陆信息获取  *  主要实现如下功能:  *  get_login_code() 获取登陆授权码, 通过授权码才能获取二维码  *  get_code_image($code='') 将上面获取的授权码转换为图片二维码  *  verify

源代码-我在学习Android 的ZXing开源项目二维码时 有几个类 不清楚他具体的意义,功能。

问题描述 我在学习Android 的ZXing开源项目二维码时 有几个类 不清楚他具体的意义,功能. ①BitMatrix.java ②ByteMatrix.java ③MultiFormatWriter.java ④QRCodeWriter.java 这4个 我实在不懂 这功能,这里面哪个 是将输入字符串 变成那个0,1 那个的?用什么算法了...我这是Android工程. 谢谢了...

打印机语言-ZPL指令设置QR code二维码无法转向的问题。

问题描述 ZPL指令设置QR code二维码无法转向的问题. 用ZPL指令生成QR CODE时,无法支持转向,该如何实现.如下^BQN,QR CODE只支持N一个参数. ^XA ^FO100,100 ^BQN,2,10 ^FD1234567890123456^FS ^XZ

MFC程序,数字图像,检测到边缘、转化成二维点阵之后,如何获取关键点

问题描述 MFC程序,数字图像,检测到边缘.转化成二维点阵之后,如何获取关键点 背景:在做毕设,题目是基于单幅数字图像进行瓷器的三维重建,导师给的思路是对瓷器的正视图进行边缘检测,然后对获取的边缘进行处理,得到完整的母线,最后将母线上的点作为样条线的控制点导入3dsmax中车削建模. 问题:我现在已经能够处理得到单像素母线轮廓了,但是像素点太密了,直接导入建模数据量太大,所以想在母线上提取关键点,我现在觉得可能是和曲线拟合相关,但具体不是很有思路,想问问大家 解决方案 非刚体怎么提取关键点,这个