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. $\mathcal{Miemeng}$的病态码风计划

    晚上困的要命,先写个码风计划提提神. 计划目标 抵制无理压行. 抵制不可读代码. 倡导代码艺术化,分层化 具体的一些细节和展示 1>整体 首先要把预读部分(我这么叫的),命名域使用,全局变量定义 ...

  2. linux基础指令参数

    eth0,eth1,eth2--代表网卡一,网卡二,网卡三-- lo代表127.0.0.1,即localhost 参考: Linux命令:ifconfig 功能说明:显示或设置网络设备 语 法:ifc ...

  3. 前端--HTML简介

    软件开发架构: c/s架构 客户端 服务端 b/s架构 浏览器 服务端 本质:b/s架构也是c/s架构 HTTP协议 超文本传输协议:规定了客户端与服务端之间消息传输的格式 四个特性: 1.基于TCP ...

  4. 洛谷P1006 NOIP提高组2008 传纸条

    P1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无 ...

  5. 两张图搞清composer install与update区别 - 今日头条(www.toutiao.com)

    composer update : 主要是在开发阶段使用,根据我们在composer.json文件中指定的内容升级项目的依赖包. composer install : 主要是在部署阶段使用,以便在生产 ...

  6. 引用CDN内容的方法总结

    1.1.1 摘要 CDN相信大家都听说过,甚至使用过相关的技术,也许有些人会回答“没有听说过和使用过该技术”,真的是这样吗? CDN的全称是Content Delivery Network,即内容分发 ...

  7. OpenSmtp 发送邮件

    1.采用发送一个简单邮件 示例: private int smtpPort; private string smtpHost; private int recieveTimeout; private ...

  8. LintCode刷题笔记-- Edit distance

    标签:动态规划 描述: Given two words word1 and word2, find the minimum number of steps required to convert wo ...

  9. 替换文本:将文本文件中的所有src替换为dst

    题意: 将文本文件中的所有src替换为dst 方法一:使用String import java.io.File; import java.io.FileNotFoundException; impor ...

  10. Python学习笔记(三)Python基本数字类型及其简单操作(1)

    一.数字类型 表示数字或数值的数据类型称为数字类型,Python语言提供3种数字类型:整数.浮点数和复数,分别对应数学中的整数.实数和复数,下面就一起来了解一下他们吧! 1.整数类型 整数类型与数学中 ...