HDOJ(1348)二维凸包
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)二维凸包的更多相关文章
- 使用Graham扫描法求二维凸包的一个程序
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...
- luogu P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows
题解: 二维凸包裸题 按照x坐标为第一关键字,y坐标为第二关键字排序 然后相邻判断叉积用单调队列搞过去 正反都做一次就好了 代码: #include <bits/stdc++.h> usi ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- 【洛谷 P2742】【模板】二维凸包
题目链接 二维凸包板子..有时间会补总结的. #include <cstdio> #include <cmath> #include <algorithm> usi ...
- poj 2079 Triangle (二维凸包旋转卡壳)
Triangle Time Limit: 3000MS Memory Limit: 30000KB 64bit IO Format: %I64d & %I64u Submit Stat ...
- poj 2187 Beauty Contest(二维凸包旋转卡壳)
D - Beauty Contest Time Limit:3000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u ...
- UVA 10652 Board Wrapping(二维凸包)
传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...
- 【计算几何】二维凸包——Graham's Scan法
凸包 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包. 一组平面上的点, ...
- 计算几何 二维凸包问题 Andrew算法
凸包:把给定点包围在内部的.面积最小的凸多边形. Andrew算法是Graham算法的变种,速度更快稳定性也更好. 首先把全部点排序.依照第一keywordx第二keywordy从小到大排序,删除反复 ...
- luogu P2742 【模板】二维凸包
嘟嘟嘟 没错,我开始学凸包了. 其实挺简单的. 前置技能: 1.极坐标系 2.向量叉积 1.极坐标系 就是一种二维坐标系.只不过两个坐标分别表示向量和极轴的角度和自身的长度.对于不同的问题,极轴可以自 ...
随机推荐
- 使用图灵机器人API实现聊天机器人
使用图灵机器人的API需要先注册,获取key才行,这我就不说了,自己到http://www.tuling123.com/注册一个账号即可. 下面就是一个简单的python调用API实现聊天机器人的简易 ...
- [LeetCode] 8. String to Integer (atoi)
Implement atoi to convert a string to an integer. public class Solution { public int myAtoi(String s ...
- 读取 java.nio.ByteBuffer 中的字符串(String) 写入方式flash.utils.ByteArray.writeUTF
通过研究ByteArray的写入格式以及方法说明,可以发现writeUTF是先使用2位写入字符串的长度,然后在其后写入字符串编码. flash.utils.ByteArray.writeUTF(val ...
- myeclipse2015CI Server显示derby服务器去除方法
找到myeclipse的安装目录 myeclipse2015CI\configuration\org.eclipse.equinox.simpleconfigurator 打开文件bundles.in ...
- viewPager--viewpager时,发生内存溢出OOM问题
两个问题:1.如果图片达到500kb每张,你这个划屏会有顿卡:2.快速滑动有出现0.几秒的白屏.图片越大,顿卡越明显. 回复parcool:500kb的背景算大的了,如果是想做图片墙,viewpage ...
- thinkphp关闭调试模式(APP_DEBUG => false),导致程序出错
thinkphp关闭调试模式(APP_DEBUG => false),导致程序出错,开启调试模式,不报错,怎么解决? 查看Logs日志记录: [ --29T09::+: ] 113.108.11 ...
- JS获取上个月(转)
1.yyyy-mm-dd获取上个月 function getUpMonth(t){ var tarr = t.split('-'); var year = tarr[0]; //获取当前日期的年 va ...
- Nginx跨域配置方法
配置文件如下,重点在49~52行 #user nobody; worker_processes ; #error_log logs/error.log; #error_log logs/error.l ...
- Visual Studio 2013 添加新项缺失[ADO.NET 实体数据模型]解决方法
解决方法如下: 1).到 Visual Studio 2013 的安装包的目录:/packages/EFTools 中寻找如下文件 EFTools.msi; EFTools.cab,如图 将它们复制自 ...
- CentOS7:搭建SVN + Apache 服务器
1. 安装httpd 安装httpd服务: $ sudo yum install httpd 检查httpd是否安装成功: $ httpd -version Server version: Apach ...