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. mac java 安装路径

    google了一下,发现了这篇文章Important Java Directories on Mac OS X,可以使用工具命令"/usr/libexec/java_home"来定 ...

  2. 【java】之3种方式实现Object和Map之间的转换

    利用commons.BeanUtils实现Obj和Map之间转换,这种是最简单,也是最经常用的 public static Object mapToObject(Map<String, Obje ...

  3. Github使用指南-从新手到专家

    转载自:http://www.cnblogs.com/xirongliu/p/4589834.html 个人从刚刚开始接触github,啥都不知道,不会用,不知道能够用来干什么,到现在坚持在githu ...

  4. js点击后将文字复制到剪贴板,将图片复制到剪贴板

    复制文字: <table width="99%" border="0" cellpadding="0" cellspacing=&qu ...

  5. 写出形似QML的C++代码

    最开始想出的标题是<Declarative C++ GUI库>,但太标题党了.只写了两行代码,连Demo都算不上,怎么能叫库呢……后来想换掉“库”这个字,但始终找不到合适词来替换.最后还是 ...

  6. Activiti开启SQL Log

    log4j.logger.org.activiti.engine.impl.persistence.entity=trace

  7. about Internet protocol

    <1> SSL版本 测试浏览器支持的SSL版本的网站: https://www.ssllabs.com/ssltest/viewMyClient.html 0xfefd    (DTLS ...

  8. Django 之 models的 F() 和 Q() 函数

    前提: app名称为core,models.py 如下: #coding: utf8 import datetime from django.db import models class Order( ...

  9. 更改yum源地址

    1.进入yum配置文件目录:cd /etc/yum.repos.d/ 2.备份配置文件:mv CentOS-Base.repo CentOS-Base.repo.bak 3.下载网易的配置,改成网易的 ...

  10. VMware Workstation 11, 客户机Ubuntu14.04.1 LTS 64bit,宿主机Windows 8.1 64bit,剪贴板共享(copy and paste)失效问题

    Ubuntu14.04是从12.04升级上来的,因为GUI性能的原因相继装了Xubunbu和Lubuntu的包(Lubuntu的桌面果然轻量级,但是请神容易送神难,卸载Xubuntu很麻烦,就先放下了 ...