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. angular4 自定义表单组件

    自定义表单组件分为单值组件和多值组件. 单值组件:input/select/radio/textarea 多值组件:checkbox/tree组件 条件: 1.必须实现ControlValueAcce ...

  2. 学习JDK1.8集合源码之--PriorityQueue

    1. PriorityQueue简介 PriorityQueue是一种优先队列,不同于普通队列的先进先出原则,优先队列是按照元素的优先级出列,每次出列都是优先级最高的元素.优先队列的应用很多,最典型的 ...

  3. 洛谷P2912 [USACO08OCT]牧场散步Pasture Walking [2017年7月计划 树上问题 01]

    P2912 [USACO08OCT]牧场散步Pasture Walking 题目描述 The N cows (2 <= N <= 1,000) conveniently numbered ...

  4. SVN客户端操作(clean up|commit|update)系统找不到指定的文件

    前天电脑中毒,更新SVN的时候,发现以下错误: Can't open file 'XXXXX\.svn\pristine\7a\7ab8cc591cd8b0425a0e6331cc52756d15ba ...

  5. OpenLayers添加地图标记

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head ...

  6. C++学习笔记(2)---2.5 C++函数编译原理和成员函数的实现

    转载自:http://c.biancheng.NET/cpp/biancheng/view/2996.html点击打开链接 从上节的例子可以看出,对象的内存模型中只保留了成员变量,除此之外没有任何其他 ...

  7. css清除浮动各方法与原理

    说到清除浮动的方法,我想网络上应该有不下7,8的方法,介绍这些方法之前,想下为什么清除浮动? 再次回到float这个属性,浮动元素(floats)会被移出文档流,不会影响到块状盒子的布局而只会影响内联 ...

  8. 去掉CSS赘余代码,CSS可以更简洁

    本篇文章适合css新手学习,对于已经掌握了css的朋友们也可以通过本片文章来复习知识. 作者通过实践,认为在有些情况下css的代码是可以更加简洁的,多数情况下是因为新手对于一些具有多属性的元素代码不能 ...

  9. 【Pyqt5】之高级控件QTableWidget的使用

    1:动态渲染数据+动态添加控件(按钮,进度条) class MainWindow(QWidget, Ui_MainFrom): def __init__(self): super(MainWindow ...

  10. 从零起步 系统入门Python爬虫工程师

    从零起步 系统入门Python爬虫工程师 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的 ...