BZOJ1845 [Cqoi2005] 三角形面积并 扫描线 计算几何
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1845
题意概括
给出n个三角形,求其面积并。
题解
有一个很经典的扫描线题目:矩形面积并。那个比较简单,建议先去看看 —— 传送门 - 矩形面积并。
这个扫描线的算法,我之前就看过。
之前想了想,还以为是n4logn的,自己以为理解错了,所以就弃坑了一段时间。
现在再想想,原来之前思考的是对的,只是复杂度想错了。其实是n3logn的。
我们按照Y来排序,同样的,我们来看一组图片。






然后大概你已经深有感触了。
步骤:把所有的分成多个梯形,然后扫描线解决。
在这之前,我们需要把所有的交点都求出来。
当然,对于上例第一层和第二层的情况十分坑。第二条扫描线的有效长度不仅和其本身的参数有关,还和该边放在上面还是下面有关。
最后,诡异的是,ans要减去Eps才可以A掉。当然也有大佬不减的Orz,题目卡精度啊!
做个好人,代码后面一组数据。
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long double LD;
const int N=300+5;
const LD Eps=1e-8,Inf=1e9;
int Dcmp(LD x){
if (fabs(x)<Eps)
return 0;
return x<0?-1:1;
}
struct Point{
LD x,y;
Point (){}
Point (LD x_,LD y_){
x=x_,y=y_;
}
Point operator + (Point a){
return Point(x+a.x,y+a.y);
}
Point operator - (Point a){
return Point(x-a.x,y-a.y);
}
Point operator * (LD a){
return Point(x*a,y*a);
}
Point operator / (LD a){
return Point(x/a,y/a);
}
bool operator == (Point a){
return !Dcmp(x-a.x)&&!Dcmp(y-a.y);
}
void read(){
scanf("%Lf%Lf",&x,&y);
}
};
LD Dot(Point a,Point b){
return a.x*b.x+a.y*b.y;
}
LD Cross(Point a,Point b){
return a.x*b.y-a.y*b.x;
}
LD Cross(Point a,Point b,Point c){
return Cross(b-a,c-a);
}
struct Line{
Point a,b;
Line (){}
Line (Point a_,Point b_){
a=a_,b=b_;
}
Line Mat(){
return Line(Point(min(a.x,b.x),min(a.y,b.y)),Point(max(a.x,b.x),max(a.y,b.y)));
}
};
LD Length(Line a){
return sqrt(Dot(a.a-a.b,a.a-a.b));
}
Point Cut_Point(Line L,LD y){
Point a=L.a,b=L.b;
LD da=y-a.y,dy=b.y-a.y,dx=b.x-a.x;
if (!Dcmp(dy))
return Point(Inf,Inf);
return Point(a.x+dx/dy*da,y);
}
Line OrderedY_Line(Point a,Point b){
if (Dcmp(a.x-b.x)>0)
swap(a,b);
return Line(a,b);
}
bool cmp_x(Point a,Point b){
return Dcmp(a.x-b.x)<0;
}
bool cmp_y(Point a,Point b){
return Dcmp(a.y-b.y)<0;
}
struct Triangle{
Point P[3];
Line L[3];
void build(Point x,Point y,Point z){
P[0]=x,P[1]=y,P[2]=z;
L[0]=Line(x,y),L[1]=Line(x,z),L[2]=Line(y,z);
}
Line Cut(int type,LD Y,bool &flag){
flag=1;
Point P_[3];
for (int i=0;i<3;i++)
P_[i]=P[i];
sort(P_,P_+3,cmp_y);
if (Dcmp(P_[1].y-Y)==0&&Dcmp(P_[2].y-Y)==0)
swap(P_[0],P_[2]);
if (Dcmp(P_[0].y-Y)==0&&Dcmp(P_[1].y-Y)==0){
if (type==0){
if (Dcmp(P_[2].y-Y)<0){
flag=0;
return Line(Point(Inf,Inf),Point(Inf,Inf));
}
return OrderedY_Line(P_[0],P_[1]);
}
else {
if (Dcmp(P_[2].y-Y)>0){
flag=0;
return Line(Point(Inf,Inf),Point(Inf,Inf));
}
return OrderedY_Line(P_[0],P_[1]);
}
}
Point p[3];
Line M[3];
for (int i=0;i<3;i++){
p[i]=Cut_Point(L[i],Y);
M[i]=L[i].Mat();
}
if (Dcmp(Y-min(M[0].a.y,M[1].a.y))<0||Dcmp(Y-max(M[0].b.y,M[1].b.y))>0){
flag=0;
return Line(Point(Inf,Inf),Point(Inf,Inf));
}
for (int i=0;i<3;i++)
if (Dcmp(Y-M[i].a.y)<0||Dcmp(Y-M[i].b.y)>0)
return OrderedY_Line(p[(i+1)%3],p[(i+2)%3]);
sort(p,p+3,cmp_x);
return OrderedY_Line(p[0],p[0]==p[1]?p[2]:p[1]);
}
};
bool Crossed(Line a,Line b){
return Dcmp(Cross(a.a,a.b,b.a))*Dcmp(Cross(a.a,a.b,b.b))<0&&Dcmp(Cross(b.a,b.b,a.a))*Dcmp(Cross(b.a,b.b,a.b))<0;
}
Point Cross_Point(Line a,Line b){
Point P=a.a,Q=b.a,v=a.b-a.a,w=b.b-b.a,u=P-Q;
LD t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
int n,m;
Triangle Tri[N];
LD Y[N*N];
bool cmp_Lx(Line a,Line b){
return Dcmp(a.a.x-b.a.x)<0;
}
LD GetLen(int type,int pos_Y){
LD y=Y[pos_Y];
Line L[N];
int tot=0;
for (int i=1;i<=n;i++){
bool flag;
L[++tot]=Tri[i].Cut(type,y,flag);
if (!flag)
tot--;
}
if (tot==0)
return 0;
sort(L+1,L+tot+1,cmp_Lx);
LD ans=L[1].b.x-L[1].a.x,max_x=L[1].b.x;
for (int i=2;i<=tot;i++){
max_x=max(max_x,L[i].a.x);
if (Dcmp(max_x-L[i].b.x)>0)
continue;
ans+=L[i].b.x-max_x;
max_x=max(max_x,L[i].b.x);
}
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
Point x,y,z;
x.read(),y.read(),z.read();
Tri[i].build(x,y,z);
}
m=0;
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
for (int u=0;u<3;u++)
for (int v=0;v<3;v++)
if (Crossed(Tri[i].L[u],Tri[j].L[v]))
Y[++m]=Cross_Point(Tri[i].L[u],Tri[j].L[v]).y;
for (int i=1;i<=n;i++)
for (int j=0;j<3;j++)
Y[++m]=Tri[i].P[j].y;
sort(Y+1,Y+m+1);
LD ans=0,pre=GetLen(0,1);
for (int i=2;i<=m;i++){
if (Dcmp(Y[i]-Y[i-1])==0)
continue;
ans+=0.5*(pre+GetLen(1,i))*(Y[i]-Y[i-1]);
pre=GetLen(0,i);
}
printf("%.2Lf",ans-Eps);
return 0;
}
数据
2
0 0 2 0 0 3
2 0 0 2 3 2
ans=5.33
数据解释:

BZOJ1845 [Cqoi2005] 三角形面积并 扫描线 计算几何的更多相关文章
- bzoj 1845: [Cqoi2005] 三角形面积并 扫描线
1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 848 Solved: 206[Submit][Statu ...
- BZOJ1845 : [Cqoi2005] 三角形面积并
求出所有交点后从左往右扫描线,用每段的中位线去截所有三角形,算出长度并后乘以该段长度即可,时间复杂度$O(n^3\log n)$. #include<cstdio> #include< ...
- BZOJ 1845: [Cqoi2005] 三角形面积并 [计算几何 扫描线]
1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 1151 Solved: 313[Submit][Stat ...
- 【BZOJ1845】[Cqoi2005] 三角形面积并 几何+扫描线
[BZOJ1845][Cqoi2005] 三角形面积并 Description 给出n个三角形,求它们并的面积. Input 第一行为n(N < = 100), 即三角形的个数 以下n行,每行6 ...
- CQOI2005 三角形面积并 和 POJ1177 Picture
1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 1664 Solved: 443[Submit][Stat ...
- [CQOI2005]三角形面积并
[CQOI2005]三角形面积并 题目大意: 求\(n(n\le100)\)个三角形的面积并. 思路: 自适应辛普森法,玄学卡精度可过. 源代码: #include<cmath> #inc ...
- BZOJ 1845: [Cqoi2005] 三角形面积并 (辛普森积分)
大力辛普森积分 精度什么的搞了我好久- 学到了Simpson的一个trick 深度开11,eps开1e-4.跑的比有些扫描线还快- CODE #include <bits/stdc++.h> ...
- UVa 11437:Triangle Fun(计算几何综合应用,求直线交点,向量运算,求三角形面积)
Problem ATriangle Fun Input: Standard Input Output: Standard Output In the picture below you can see ...
- hdu 4709:Herding(叉积求三角形面积+枚举)
Herding Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
随机推荐
- 大量界面刷新时手动Dispose也是有必要的
在winform窗体上拖一个flowLayoutPane,一个Button,项目中再创建一个用户控件UcControl,用户控件上放几十个子控件 private void button1_Click( ...
- Mysql高级查询 内连接和外连接详解
一.内连接(INNER JOIN) 1.等值连接 概述:指使用等号"="比较两个表的连接列的值,相当于两表执行笛卡尔后,取两表连结列值相等的记录. 语法: SELECT 列 FRO ...
- WIN10下安装USB转串口驱动出现“文件的哈希值不在指定的目录”的解决办法
今天安装openJTAG驱动时出现“文件的哈希值不在指定的目录”,系统为WIN10专业版. 原因是驱动无数字签名,在WIN10中是不安全的驱动,所以显示哈希值不在范围内不能安装. 经查阅已经解决,发放 ...
- 20155332 2016-2017-2 《Java程序设计》第5周学习总结
学号 2016-2017-2 <Java程序设计>第X周学习总结 教材学习内容总结 1.Java中的所有不正常类都继承于Throwable类.Throwable主要包括两个大类,一个是Er ...
- luogu P1357 花园
传送门 先考虑朴素dp,设\(f_{i,j}\)表示推了\(i\)次,前\(m\)个点的状态为二进制数\(j\)(这里记放C为1),转移的时候枚举下一位放什么,还要考虑是否满足C的个数\(\leq k ...
- kafka.common.KafkaException: Socket server failed to bind to hdp1:9092: Cannot assign requested address.
ERROR [KafkaServer id=1] Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.K ...
- 出现fonts/fontawesome-webfont.woff?v=4.5.0 net::ERR_ABORTED
虽然网页正常显示和运行,但是有2个字体文件出现404错误. 原因:服务器没有配置MIME类型而已. 1. 在IIS网站中,找打网站对应的MIME类型,双击. 2.能看到此网站对应的MIME类型,点击右 ...
- mysql 原理~ 乐观锁和悲观锁
一 简介:今天咱们来聊聊悲观锁和乐观锁 二 悲观锁 1 定义 在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC” ...
- 求web前端面试题库及答案
1.对WEB标准以及W3C的理解与认识 标签闭合.标签小写.不乱嵌套.提高搜索机器人搜索几率.使用外 链css和js脚本.结构行为表现的分离.文件下载与页面速度更快.内容能被更多的用户所访问.内容能被 ...
- awk对列/行进行统计求和【转】
场景]--类似于excel中的sum函数对列/行进行统计求和 A01 A02 A03 A09 [要求1]--对列进行统计求和 A01 A02 A03 A09 TOTAL [要求2]--对行进行统计求和 ...