Problem - 4629

  以前写过PSLG模拟的版本,今天写了一下扫描线做这题。

  其实这题可以用set存线段来做,类似于判断直线交的做法。不过实现起来有点麻烦,于是我就直接暴力求交点了。

代码如下:

 #include <set>
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm> using namespace std; const double EPS = 1e-;
inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
typedef pair<double, double> Point;
#define x first
#define y second
Point operator + (Point a, Point b) { return Point(a.x + b.x, a.y + b.y);}
Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y);}
Point operator * (Point a, double p) { return Point(a.x * p, a.y * p);}
Point operator / (Point a, double p) { return Point(a.x / p, a.y / p);} inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
inline double veclen(Point a) { return sqrt(dot(a, a));}
inline Point rotate(Point a) {
double cosx = cos(0.001), sinx = sin(0.001);
return Point(a.x * cosx - a.y * sinx, a.x * sinx + a.y * cosx);
} struct Line {
Point s, t;
Line() {}
Line(Point s, Point t) : s(s), t(t) {}
Point vec() { return t - s;}
Point point(double p) { return s + vec() * p;}
} ;
inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
void scan(Point &a) { cin >> a.x >> a.y;}
const int N = ;
Point tri[N][]; bool check(int n) {
for (int i = ; i < n; i++) {
for (int j = ; j < ; j++) {
if (sgn(tri[i][j].x - tri[i][j + ].x) == ) return ;
}
}
return ;
}
void adjust(int n) { for (int i = ; i < n; i++) for (int j = ; j < ; j++) tri[i][j] = rotate(tri[i][j]);}
inline bool between(Point p, Point a, Point b) { return sgn(dot(a - p, b - p)) <= ;}
bool cmpy(Point a, Point b) { return a.y < b.y;} bool triline(Line l, int id, Point *ip) {
Point tmp[];
int tt = ;
for (int i = ; i < ; i++) {
tmp[tt] = llint(l, Line(tri[id][i], tri[id][i + ]));
if (between(tmp[tt], tri[id][i], tri[id][i + ])) tt++;
}
sort(tmp, tmp + tt, cmpy);
ip[] = tmp[], ip[] = tmp[tt - ];
return tt > ;
} typedef pair<double, int> Break;
bool cmp(Break a, Break b) { return sgn(a.x - b.x) < || sgn(a.x - b.x) == && a.y < b.y;}
Break ips_l[N << ], ips_r[N << ];
double area[N], len_l[N], len_r[N], event[N * N << ];
void scanline(int n) {
memset(area, , sizeof(area));
int tt = ;
for (int i = ; i < n; i++) {
for (int j = ; j < ; j++) {
Point a = tri[i][j], b = tri[i][j + ];
event[tt++] = a.x;
for (int k = ; k < n; k++) {
for (int l = ; l < ; l++) {
Point c = tri[k][l], d = tri[k][l + ];
if (sgn(cross(b - a, d - c)) == ) continue;
Point ip = llint(Line(a, b), Line(c, d));
//cout << ip.x << ' ' << ip.y << endl;
if (between(ip, a, b) && between(ip, c, d)) {
event[tt++] = ip.x;
}
}
}
}
}
sort(event, event + tt);
tt = (int) (unique(event, event + tt) - event);
Line cur;
Point tmp[];
for (int i = , c, cnt; i < tt; i++) {
if (sgn(event[i - ] - event[i]) == ) continue;
c = ;
cur = Line(Point(event[i - ] + EPS, 0.0), Point(event[i - ] + EPS, 1.0));
for (int j = ; j < n; j++) {
if (triline(cur, j, tmp)) {
ips_l[c++] = Break(tmp[].y, ), ips_l[c++] = Break(tmp[].y, -);
}
}
sort(ips_l, ips_l + c, cmp);
cnt = ;
memset(len_l, , sizeof(len_l));
for (int j = ; j < c; j++) {
if (cnt > ) len_l[cnt] += ips_l[j].x - ips_l[j - ].x;
cnt += ips_l[j].y;
}
c = ;
cur = Line(Point(event[i] - EPS, 0.0), Point(event[i] - EPS, 1.0));
for (int j = ; j < n; j++) {
if (triline(cur, j, tmp)) {
ips_r[c++] = Break(tmp[].y, ), ips_r[c++] = Break(tmp[].y, -);
}
}
sort(ips_r, ips_r + c, cmp);
cnt = ;
memset(len_r, , sizeof(len_r));
for (int j = ; j < c; j++) {
if (cnt > ) len_r[cnt] += ips_r[j].x - ips_r[j - ].x;
cnt += ips_r[j].y;
}
for (int j = ; j <= n; j++) area[j] += (len_l[j] + len_r[j]) * (event[i] - event[i - ]) / ;
}
} int main() {
ios::sync_with_stdio();
cout << setiosflags(ios::fixed) << setprecision();
int T, n;
cin >> T;
while (T-- && cin >> n) {
int tt = ;
for (int i = ; i < n; i++) {
for (int j = ; j < ; j++) scan(tri[tt][j]);
tri[tt][] = tri[tt][];
if (sgn(cross(tri[tt][] - tri[tt][], tri[tt][] - tri[tt][]))) tt++;
}
while (check(tt)) adjust(tt);
scanline(tt);
for (int i = ; i <= n; i++) area[i] = fabs(area[i]);
for (int i = ; i <= n; i++) cout << area[i] << endl;
}
return ;
}

——written by Lyon

hdu 4629 Burning (扫描线)的更多相关文章

  1. HDU 4629 Burning 几何 + 扫描线

    总体思路参考了 这里. 细节:1.控制精度,虽然这题没卡精度,不过还是要控制一下. 之前 bool operator<( const Point& A, const Point& ...

  2. HDU 3511 圆扫描线

    找最深的圆,输出层数 类似POJ 2932的做法 圆扫描线即可.这里要记录各个圆的层数,所以多加一个维护编号的就行了. /** @Date : 2017-10-18 18:16:52 * @FileN ...

  3. (中等) HDU 3265 Posters , 扫描线。

    Problem Description Ted has a new house with a huge window. In this big summer, Ted decides to decor ...

  4. hdu 3255 Farming(扫描线)

    题目链接:hdu 3255 Farming 题目大意:给定N个矩形,M个植物,然后给定每一个植物的权值pi,pi表示种植物i的土地,单位面积能够收获pi,每一个矩形给定左下角和右上角点的坐标,以及s, ...

  5. Atlantis HDU - 1542 (扫描线,线段树)

    扫描线的模板题,先把信息接收,然后排序,记录下上边和下边,然后用一条虚拟的线从下往上扫.如果我扫到的是下边,那么久用线段树在这个区间内加上1,表示这个区间现在是有的,等我扫描到上边的时候在加上-1,把 ...

  6. 覆盖的面积 HDU - 1255(扫描线求面积交)

    题意: 就是扫描线求面积交 解析: 参考求面积并.... 就是把down的判断条件改了一下..由w > 0 改为 w > 1 同时要讨论一下 == 1 时  的情况, 所以就要用到一个临时 ...

  7. POJ 1151 HDU 1542 Atlantis(扫描线)

    题目大意就是:去一个地方探险,然后给你一些地图描写叙述这个地方,每一个描写叙述是一个矩形的右下角和左上角.地图有些地方是重叠的.所以让你求出被描写叙述的地方的总面积. 扫描线的第一道题,想了又想,啸爷 ...

  8. 覆盖的面积 HDU - 1255 (扫描线, 面积交)

    求n个矩阵面积相交的部分,和求面积并一样,不过这里需要开两个数组保存覆盖一次和覆盖两次以上的次数的部分,还是模板,主要注意点就是pushup部分,如果我已经被两次覆盖,那我的两个数组在这个root点的 ...

  9. Get The Treasury HDU - 3642(扫描线求三维面积交。。体积交)

    题意: ...就是求体积交... 解析: 把每一层z抽出来,计算面积交, 然后加起来即可..! 去看一下 二维面积交的代码 再看看这个三维面积交的代码.. down函数里 你发现了什么规律!!! 参考 ...

随机推荐

  1. php用mysql方式连接数据库出现Deprecated报错

    以上是用php5.5 连接mysql数据库时报的错. 于是我用php5.4 连接正常没有报错. 这与mysql版本无关系,php 5.x版本,如5.2.5.3.5.4.5.5,怕跟不上时代,新的服务器 ...

  2. MySQL下载安装详情教程(Windows)

    1.下载MySQL数据库可以访问官方网站:https://www.mysql.com/ 2.点击DOWNLOADS模块下的Community模块下的MySQL Community Server进行下载 ...

  3. uva 11300 分金币(利用绝对值加和进行求出最小值)

    //qq 767039957 welcome #include<cstdio> #include<algorithm> #include<vector> #incl ...

  4. 洛谷P1002 过河卒 [2017年4月计划 动态规划15]

    P1002 过河卒 题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之 ...

  5. 低价替代Vector CANoe CAN总线适配解决方案支持所有USBCAN(周立功CAN、PCAN、Kvaser、ValueCAN、NI CAN)

    在汽车通信领域CAN总线使用非常广泛,最强大的工具有Vector Case(10WRMB).Pcan(2KRMB),ZLGCAN(1.5KRMB),KVASER(2KRMB).ValueCAN(4KR ...

  6. webpack 4.X 创建 react项目

    1. 新建一个文件夹2. 运行 npm init -y 快速初始化项目3. 在跟目录创建src文件夹 dist文件夹4. 在src下创建 index.html main.js // index.htm ...

  7. web前端学习(二)html学习笔记部分(2)-- 改良的元素(input元素等等)

    1.2.5  HTML5 改良的 input 元素的种类 1.2.5.1  新增的input元素种类中的改良与增加 input 元素的种类 (1) 新增的input元素种类中的url类型.email类 ...

  8. Ubuntu 12.04 安装 IQQ

    1. 安装 IQQ 首先应安装jdk包 2. 百度网盘下载: http://pan.baidu.com/share/home?uk=3071047022 3. 运行 (1) Linux用户给IQQ-1 ...

  9. tomcat的日志不输出日志信息的解决方法

    1.下载日志jar包,例如:commons-logging-1.1.1.jar.放在tomcat的bin目录下,或者是自己项目的lib包里. 2.修改tomcat的bin目录下面的catalina.b ...

  10. [J2EE规范]JDBC简单例子 标签: 数据库j2eejdbcjava 2017-06-29 10:55 353人阅读 评论(12)

    JDBC是什么? JDBC是java数据库连接(Java Database Connectivity),它是用于java编程语言和数据库之间的数据库无关连接的标准Java API,就是说,JDBC是用 ...