题意就是给你很多个半平面,求半平面交出来的凸包的面积。

半平面交有O(n^2)的算法,就是每次用一个新的半平面去切已有的凸包,更新,这个写起来感觉也不是特别好写。

另外一个O(nlogn)的算法是将半平面交极角排序,然后用一个双端队列去维护半平面交,每次加入一个半平面,根据之前的交点的位置退掉半平面,方法跟凸包非常相像,(不同的是加入队列的时候还要考虑加入半平面会使队首的平面变得无效,因为会有两个while.最后还要考虑最后加入的半平面绕了一圈之后使得队首的半平面变得无效。)其实这里有点不太懂后面再慢慢补一补吧。

下面的代码用的是CLJ的模板,看大神写的模板能学习到很多东西。我对于计算几何还是不太熟悉,因为如何利用cross求很多东西其实都不太熟,例如如何用cross求两直线的交点。还有里面的border的极角排序的<重载,unique去重时需要的==重载。更高深的原理日后慢慢研究。。- -0

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <string>
#include <algorithm>
using namespace std; #define maxn 25000
#define eps 1e-8 int n; int dcmp(double x){
return (x > eps) - (x < -eps);
} struct Point
{
double x, y;
Point(){}
Point(double _x, double _y) :x(_x), y(_y){}
Point operator + (const Point &b) const{
return Point(x + b.x, y + b.y);
}
Point operator - (const Point &b) const{
return Point(x - b.x, y - b.y);
}
Point operator *(double d) const{
return Point(x*d, y*d);
}
Point operator /(double d) const{
return Point(x / d, y / d);
}
double det(const Point &b) const{
return x*b.y - y*b.x;
}
double dot(const Point &b) const{
return x*b.x + y*b.y;
}
}; #define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) (dcmp(cross(p1,p2,p3))) Point isSS(Point p1, Point p2, Point q1, Point q2){
double a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
return (p1*a2 + p2*a1) / (a1 + a2);
} struct Border
{
Point p1, p2;
double alpha;
void setAlpha(){
alpha = atan2(p2.y - p1.y, p2.x - p1.x);
}
bool operator < ( const Border &b) const{
int c = dcmp(alpha - b.alpha);
if (c != 0) return c == 1;
return crossOp(b.p1, b.p2, p1) >= 0;
}
bool operator == (const Border &b) const{
return dcmp(alpha - b.alpha) == 0;
}
}; Point isBorder(const Border &a, const Border &b){
return isSS(a.p1, a.p2, b.p1, b.p2);
} Border border[maxn];
Border que[maxn];
int qh, qt;
// check函数判断的是新加的半平面和由a,b两个半平面产生的交点的方向,若在半平面的左侧返回True
bool check(const Border &a, const Border &b,const Border &me){
Point is = isBorder(a, b);
return crossOp(me.p1, me.p2, is) > 0;
} void convexIntersection()
{
qh = qt = 0;
sort(border, border + n);
n = unique(border, border + n) - border;
for (int i = 0; i < n; i++){
Border cur = border[i];
while (qh + 1 < qt&&!check(que[qt - 2], que[qt - 1], cur)) --qt;
while (qh + 1 < qt&&!check(que[qh], que[qh + 1], cur)) ++qh;
que[qt++]=cur;
}
while (qh + 1 < qt&&!check(que[qt - 2], que[qt - 1], que[qh])) --qt;
while (qh + 1 < qt&&!check(que[qh], que[qh + 1], que[qt-1])) ++qh;
} Point ps[maxn]; int main()
{
while (cin >> n)
{
for (int i = 0; i < n; i++){
scanf("%lf%lf%lf%lf", &border[i].p1.x, &border[i].p1.y, &border[i].p2.x, &border[i].p2.y);
}
border[n].p1.x = 0; border[n].p1.y = 0; border[n].p2.x = 10000; border[n].p2.y = 0;
border[n+1].p1.x = 10000; border[n+1].p1.y = 0; border[n+1].p2.x = 10000; border[n+1].p2.y = 10000;
border[n+2].p1.x = 10000; border[n+2].p1.y = 10000; border[n+2].p2.x = 0; border[n+2].p2.y = 10000;
border[n+3].p1.x = 0; border[n+3].p1.y = 10000; border[n+3].p2.x = 0; border[n+3].p2.y = 0;
n = n + 4;
for (int i = 0; i < n; i++){
border[i].setAlpha();
}
convexIntersection();
int cnt = 0;
if (qt - qh <= 2){
puts("0.0"); continue;
}
for (int i = qh; i < qt; i++){
int nxt = i + 1 == qt ? qh : i + 1;
ps[cnt++] = isBorder(que[i], que[nxt]);
}
double area = 0;
for (int i = 0; i < cnt; i++){
area += ps[i].det(ps[(i + 1) % cnt]);
}
area /= 2;
area = fabs(area);
printf("%.1lf\n", area);
}
return 0;
}

POJ2451 Uyuw's Concert(半平面交)的更多相关文章

  1. POJ 2451 Uyuw's Concert (半平面交)

    题目链接:POJ 2451 Problem Description Prince Remmarguts solved the CHESS puzzle successfully. As an awar ...

  2. POJ2451 Uyuw's Concert (半平面交)

    POJ2451  给定N个半平面 求他们的交的面积. N<=20000 首先参考 POJ1279 多边形的核 其实就是这里要求的半平面交 但是POJ1279数据较小 O(n^2)的算法 看起来是 ...

  3. [poj2451]Uyuw's Concert

    半平面交滴裸题,但是要求nlogn,练练手 #include<iostream> #include<cstdio> #include<cmath> #include ...

  4. poj2451Uyuw's Concert(半平面交)

    链接 逆时针给出线段,如果模板是顺时针的修改下系数的符号进行平面交即可. #include <iostream> #include<cstdio> #include<cs ...

  5. poj 2451 Uyuw's Concert (半平面交)

    2451 -- Uyuw's Concert 继续半平面交,这还是简单的半平面交求面积,不过输入用cin超时了一次. 代码如下: #include <cstdio> #include &l ...

  6. poj 2451 Uyuw's Concert(半平面交)

    Uyuw's Concert Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 8580   Accepted: 3227 De ...

  7. 半平面交总结and模板

    博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40859973 这两天刷了POJ上几道半平面交,对半平面交有了初步的体会,感觉半 ...

  8. poj 2451 Uyuw's Concert

    [题目描述] Remmarguts公主成功地解决了象棋问题.作为奖励,Uyuw计划举办一场音乐会,地点是以其伟大的设计师Ihsnayish命名的巨大广场. 这个位于自由三角洲联合王国(UDF,Unit ...

  9. 【POJ 3525】Most Distant Point from the Sea(直线平移、半平面交)

    按逆时针顺序给出n个点,求它们组成的多边形的最大内切圆半径. 二分这个半径,将所有直线向多边形中心平移r距离,如果半平面交不存在那么r大了,否则r小了. 平移直线就是对于向量ab,因为是逆时针的,向中 ...

随机推荐

  1. python 中 input 和 raw_input 的区别

    input会假设输入的信息是合法的python表达式,例如,输入一个人名,Diesel,input会认为这是一个变量,必须加上引号,比如“Diesel”: 而raw_input会把所有的输入当作原始数 ...

  2. Windows上搭建android开发环境

    在搭建android开发环境时需要四部分内容,框架如下 其中Java SDK和Eclipse在java4android中有过介绍,重点介绍ADT和Android SDK的安装. 安装Android S ...

  3. linux内核设计与实现学习笔记-模块

    模块 1.概念:  如果让LINUX Kernel单独运行在一个保护区域,那么LINUX Kernel就成为了“单内核”.    LINUX Kernel是组件模式的,所谓组件模式是指:LINUX K ...

  4. oracle 分析函数(笔记)

    分析函数是oracle数据库在9i版本中引入并在以后版本中不断增强的新函数种类.分析函数提供好了跨行.多层次聚合引用值的能力.分析函数所展现的效果使用传统的SQL语句也能实现,但是实现方式比较复杂,效 ...

  5. [原创] PostgreSQL Plus Advanced Server在Windows中配置双机热备流复制

    一.系统环境 操作系统:Windows Server 2003/2008 两个节点分别为master与slave. 主节点master:172.27.19.28 备机点slave:172.27.19. ...

  6. db2查询锁表

    --查询锁表情况,可以获取哪个表被锁,其中agent_id为哪个DB2进程锁了表(db2inst1用户下) select * from sysibmadm.LOCKS_HELD with ur; -- ...

  7. Split字符串分割函数

    非常非常常用的一个函数Split字符串分割函数. Dim myTest myTest = "aaa/bbb/ccc/ddd/eee/fff/ggg" Dim arrTest arr ...

  8. 46.谈谈SDRAM的作用

    SDRAM这个至今还在用的存储器,虽然被后来的DDR取代,掌握好它还是很重要的.之前在调试时,确实费了好大劲,它的复杂性毋庸置疑,一般人要想弄懂他,得花1个月左右吧,至少我这么认为.话说回来,SDRA ...

  9. linux校准时间

    Linux下ntpdate时间同步 Ntp服务器安装配置 ntp(Network Time Protocol)协议 RedHat服务器可以下载rpm安装包,然后执行# rpm -ivh ntp-4.2 ...

  10. [shell基础]——数组

    数组赋值 1. 逐个数组元素赋值 # array[0]=11 # array[1]=22 # array[2]=33 # echo ${array[@]} 11 22 33 33 2. array( ...