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

半平面交有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. 【转】Winform下KeyDown,KeyPress,KeyUp事件的总结

    http://blog.csdn.net/xiashengwang/article/details/6777907

  2. python中的多继承

    python和C++一样,支持多继承.概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性. class P1 #( ...

  3. WIN服务器出现 php-cgi.exe - FastCGI 进程意外退出

    既然是不能解析PHP,那就直接运行一下PHP,看会报什么错,再对症下药,于是,在命令提示符窗口进入php安装的根目录,然后运行php -v的命令,这时窗口弹出计算机丢失msvcr110.dll的错误, ...

  4. mac下163企业邮箱客户端的配置

    一 添加账户       添加账户->添加其他邮件账户->输入电子邮件地址和密码.(全名随意起).   二 收件服务器和发件服务器的设置       收件服务器:pop.qiye.163. ...

  5. extjs 表格可复制

    在GridPanel的配置项中,加入这个配置就可以了: viewConfig:{ enableTextSelection:true }

  6. 各设备如何清理dns缓存

    Windows 按下 Windows+R 键,运行 cmd ,在命令提示符运行命令 ipconfig /flushdns OS X 10.10 在[应用程序][实用工具][终端]运行命令 sudo d ...

  7. EF6 在原有数据库中使用 CodeFirst 总复习(二、新的需求,简单修改原有表)

    一.为当前实体模型启用数据迁移 基础搭建好了,也就是原有的数据库有了,原有数据库的实体对象也有了,但生成的上下文中并没有标记当前数据库是否已经存在,当前实体是否修改过(以前版本好像有标记的),所以,要 ...

  8. 我的VS2013中,用Ado.net给SQLParameter赋值的时候,当赋值null的时候,生成的sql语句是default

    /// <summary> /// 增加一条数据 /// </summary> public bool Add(Model.WechatDocuments model) { S ...

  9. Qt 按键长按的处理

    keyPressEvent()部分代码: if (e->key() == Qt::Key_A && e->isAutoRepeat()) {   if (!mPressFl ...

  10. 在EDK里面添加ISE IP core的方法

    (1)在ISE下,使用core generator,可以得到xilinx的IP的*.v和*.ngc 文件,将这两个文件拷贝出来: (2)在EDK下使用“Create or Import Periphe ...