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. js随机颜色生成

    return '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6);

  2. 将 Shiro 作为应用的权限基础

    Shiro 是 Java 世界中新近出现的权限框架,较之 JAAS 和 Spring Security,Shiro 在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势.本文介绍了 Shiro 的 ...

  3. vscode配置

    默认的挺难看的 颜色主题换成 Monokai Dimmed 用户设置 // 将设置放入此文件中以覆盖默认设置 { "editor.fontFamily": "Monaco ...

  4. C# 图片流下载;图片流输出

    图片流下载 string filePath = HttpContext.Current.Server.MapPath("/img/wxPic/"); if (!Directory. ...

  5. CodeSmith模板

    重复性的工作交给代码生成器就好,这里分享几套模板, 1.从数据库抓取字段,生成Table元素,这个在web开发中很有用 <%-- Name: Author: Description: --%&g ...

  6. HBase内部操作日志说明

    版本:0.94-cdh4.2.1 1. Split Region [regionserver60020-splits-1397585864985] INFO org.apache.hadoop.hba ...

  7. Apache配置文件服务器

    配置Apache文件服务器: apache配置文件服务器httpd.conf中这两个模块必须不被注释LoadModule autoindex_module modules/mod_autoindex. ...

  8. stickUp让页面元素“固定”位置

    stickUp能让页面目标元素“固定”在浏览器窗口的顶部,即便页面在滚动,目标元素仍然能出现在设定的位置. http://www.bootcss.com/p/stickup/

  9. 2、NASA HS3(Hurricane AND Server Storm Sentinel)

    国内访问不到,但是通过ppt可以看到,数据支撑做的很到位,前台展示很炫.  气象领域WebGL应用最好案例的当之无愧啊.这篇全部贴图了. 来自为知笔记(Wiz)

  10. maven多项目配置实践

    工具:IntelliJ IDEA 1.新建maven项目top 略 提示:不使用任何模版 2.在上面的maven项目的目录下(虽然这不一定是必须的),新建另一个maven项目secend. 同上 3. ...