Wall

http://acm.hdu.edu.cn/showproblem.php?pid=1348

题目描述:有个国王想在他的城堡外面修围墙,围墙与城堡的最小距离为L,要求围墙长度最短。求围墙的长度。(哎~~,每个人心里都有一座墙,King可不例外。)

算法:围墙可看作城堡(输入的顶点)构成的凸包,各边长度不变,向外平移L,各个角的围墙拼起来就是一个半径为L的完整的圆。

就那题目给的图来说吧

不得不说本人学的PS还是很有用的。。。

先贴这题的源代码

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const double eps=1e-;
struct Node
{
int x,y;
Node operator-(Node &node) //运算符重载,需要用C++提交
{
Node new_node;
new_node.x=x-node.x;
new_node.y=y-node.y;
return new_node;
}
Node operator+(Node &node)
{
Node new_node;
new_node.x=x+node.x;
new_node.y=y+node.y;
return new_node;
}
};
vector<Node> s; //这里用vector来模拟栈,相比用stack,vector可以访问非栈顶元素,比较方便
Node *p; void swap(Node &a,Node &b)
{
Node temp;
temp=a;
a=b;
b=temp;
}
double cross(Node vec1,Node vec2)
{
return (double)vec1.x*vec2.y-(double)vec1.y*vec2.x;
}
double Distance(Node a,Node b)
{
return sqrt(((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))*1.0);
}
bool cmp(Node &p1,Node &p2)
{
double temp=cross(p1-p[],p2-p[]);
if(temp>eps)
return true;
else if(temp<-eps)
return false;
else
{
if(Distance(p1,p[])<Distance(p2,p[]))
return true;
else
return false;
}//当2个向量共线时temp<=eps,与p[0]距离大的点排在后面
}
int lowleft(Node p[],int n)
{
int px=p[].x;
int py=p[].y;
int k=;
for(int i=;i<n;i++) //先最下再最左
{
if(p[i].y<py)
{
px=p[i].x;
py=p[i].y;
k=i;
}
else if(p[i].y==py&&p[i].x<px)
{
px=p[i].x;
k=i;
}
}
return k;
}
void graham(Node p[],int n)
{
int k=lowleft(p,n);
swap(p[],p[k]);
sort(p+,p+n,cmp); //给p[1]~p[n]按相对p[0]的极角排序(逆时针)
p[n]=p[];
s.push_back(p[]);
s.push_back(p[]); int top=;
for(int i=;i<=n;i++)
{
//检查不向左转的情况,而不是对向右转进行检查,
//这样的测试排除在所形成的凸包的某个顶点处于平角的可能性
while(top>=&&cross(s[top]-s[top-],p[i]-s[top])<=) //先判断top>=1,防止出现s[-1];
{
s.pop_back();
top--;
}
s.push_back(p[i]);
top++;
}
}
int main()
{
int t,n,L;
cin>>t;
while(t--)
{
s.clear();
double sum=0.0;
cin>>n>>L;
p=new Node[n+]; //最后一个元素存p[0]
for(int i=;i<n;i++)
cin>>p[i].x>>p[i].y;
graham(p,n);
int s_len=s.size();
for(int i=;i<s_len;i++)
{
sum+=Distance(s[i-],s[i]);
}
sum+=*acos(-1.0)*L;
sum=(int)(sum+0.5);
cout<<sum<<endl;
if(t)
cout<<endl;
}
return ;
}

凸包:形象一点说,把点集Q中的每个点都想象成是露在一块板外的铁钉,那么凸包就是包围了所有这些铁钉的一条拉紧了的橡皮绳所构成的形状。(来自算法导论)

传说寻找凸包有很多方法,我才刚学了一种,Graham扫描法。我很笨拙,花了一天时间。后期学了其他方法,会有一些更新。

Graham扫描法的主要步骤:

1.先找到最下面然后最靠左边的点。

2.以它为原点,对其他点进行极角排序(这里是逆时针)。

3.将p[0],p[1]入栈,p[0]必为凸多边形的顶点,而p[1]可能处为平角。

4.按p[0]~p[n]依次去走每个点,如果在某个点准备向右转或者直走,就将这个点出栈

下面贴出Graham算法的模板:

void graham(Node p[],int n)
{
int k=lowleft(p,n);
swap(p[],p[k]);
sort(p+,p+n,cmp); //给p[1]~p[n]按相对p[0]的极角排序(逆时针)
p[n]=p[];
s.push_back(p[]);
s.push_back(p[]); int top=;
for(int i=;i<=n;i++)
{
//检查不向左转的情况,而不是对向右转进行检查,
//这样的测试排除在所形成的凸包的某个顶点处于平角的可能性
while(top>=&&cross(s[top]-s[top-],p[i]-s[top])<=) //先判断top>=1,防止出现s[-1];
{
s.pop_back();
top--;
}
s.push_back(p[i]);
top++;
}
}

HDOJ(1348)二维凸包的更多相关文章

  1. 使用Graham扫描法求二维凸包的一个程序

    #include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...

  2. luogu P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows

    题解: 二维凸包裸题 按照x坐标为第一关键字,y坐标为第二关键字排序 然后相邻判断叉积用单调队列搞过去 正反都做一次就好了 代码: #include <bits/stdc++.h> usi ...

  3. Luogu P2742 模板-二维凸包

    Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...

  4. 【洛谷 P2742】【模板】二维凸包

    题目链接 二维凸包板子..有时间会补总结的. #include <cstdio> #include <cmath> #include <algorithm> usi ...

  5. poj 2079 Triangle (二维凸包旋转卡壳)

    Triangle Time Limit: 3000MS   Memory Limit: 30000KB   64bit IO Format: %I64d & %I64u Submit Stat ...

  6. poj 2187 Beauty Contest(二维凸包旋转卡壳)

    D - Beauty Contest Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u ...

  7. UVA 10652 Board Wrapping(二维凸包)

    传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...

  8. 【计算几何】二维凸包——Graham's Scan法

    凸包 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包. 一组平面上的点, ...

  9. 计算几何 二维凸包问题 Andrew算法

    凸包:把给定点包围在内部的.面积最小的凸多边形. Andrew算法是Graham算法的变种,速度更快稳定性也更好. 首先把全部点排序.依照第一keywordx第二keywordy从小到大排序,删除反复 ...

  10. luogu P2742 【模板】二维凸包

    嘟嘟嘟 没错,我开始学凸包了. 其实挺简单的. 前置技能: 1.极坐标系 2.向量叉积 1.极坐标系 就是一种二维坐标系.只不过两个坐标分别表示向量和极轴的角度和自身的长度.对于不同的问题,极轴可以自 ...

随机推荐

  1. AVL的删除写法的一个错误

    今天在写AVL删除的时候犯了一个傻逼错误,调了很久,教训惨痛,引以为鉴. 树中允许有重复节点,如果删除的节点有重复,则只删除1个. AVL删除采取的方法是首先判断待删除节点是否存在,如果存在,那么判断 ...

  2. Install Maya 2015 x64 in CentOS 7

    Thanks for Must(QQ ID)'s big help for installing Maya in CentOS7. This is my steps for installing ma ...

  3. arduino 串口实时绘图(以mpu9250为例)

    兴趣之余,利用晚上的时间,做一些个人兴趣方面的开发. 之前没接触过 arduino, 无意之中买了个开发板做一些小开发, 这里利用python 读取 mpu9250 数据实时绘图. 下位机代码 C++ ...

  4. 解决Android SDK下载和更新失败的方法(Win系统) 和离线安装

    http://jingyan.baidu.com/article/a3a3f811f370558da2eb8a94.html http://jingyan.baidu.com/article/636f ...

  5. [杂] BOSE QC15维修小记

    有一句话大概是这样说的“其他的耳机是靠嘴说的,BOSE是靠耳朵听的”,2010年就开始馋QC3,直到2012年在Vancouver的BOSE店里,在震耳欲聋的模拟噪音中带上QC15那一刻,下了决心. ...

  6. hmtl弹出框样式

    @model Web.Manager.Models.SendMessage @{ ViewBag.Title = "消息发布"; Layout = null;} <link ...

  7. 导入 RecyclerView 控件 的过程(Android 6.0)

    由于本人不熟悉Android Studio和java的思维方式,开发android studio的同事告诉我不太推荐使用ListView 而google 建议使用RecycleView ,经过了一顿查 ...

  8. range for query

    static void range_test(Args _args) { Query                   Query; QueryRun                QueryRun ...

  9. Linux RPM、TAR包管理

    一.RPM软件包命令的使用 RPM主要有5种基本操作模式:安装.卸载.刷新.升级及查询.下面分别介绍. 1.安装软件包 命令语法: rpm -ivh [RPM包文件名称] 命令中各参数的含义如下: - ...

  10. struts2原理理解

    1.  由容器创建HttpServletRequest请求,这个请求经过一系列的过滤器,最终到struts2的核心过滤器(FilterDispatch), 2.  核心过滤器会根据url请求获得Act ...