bzoj-1845 三角形面积并

题意:

给出n个三角形,求这n个三角形的面积并;

n<=100,坐标范围在10^6之内;

题解:

裸的扫描线处理面积并问题;

计算几何的数据范围通常不会出的很大,这种题都只是考虑如何处理数据;

这道题我似乎是被卡了一点精度,double换成long double才过掉;

至于解法第一句不是说完了吗23333

咳。。首先就是为了方便处理,我们求出所有线段的交点;

然后用这些交点的横坐标将坐标系划分成一个个竖条;

这些竖条间隔的块内,一定不会出现顶点,一定都是由梯形(三角形)组成的图形;

这个性质实际上保证了一些东西,我们才可以用一些比较优美的方法解出这道题;

考虑枚举每一个块,如何计算这个块内的面积呢?

用中位线去截这个块,得到的区间并长度就是中位线总长度,而总长度*块的宽度就是面积了;

具体的细节理解还是写代码比较好,代码实现也主要是细节;

时间复杂度O(n^3logn),但是写这种题别太纠结复杂度,100范围而已= =;

实现上还是要随心所欲吧,计算几何中写对比写的快重要得多咯;

代码:

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 333
#define pr pair<ld,ld>
using namespace std;
typedef long double ld;
const ld EPS=1e-8;
const ld INF=1e100;
struct Point
{
	ld x,y;
	Point(){}
	Point(ld _,ld __):x(_),y(__){}
	void read()
	{
		double _,__;
		scanf("%lf%lf",&_,&__);
		x=_,y=__;
	}
	friend bool operator <(Point a,Point b)
	{
		if(fabs(a.x-b.x)<EPS)
		return a.y<b.y;
		return a.x<b.x;
	}
	friend Point operator +(Point a,Point b)
	{
		return Point(a.x+b.x,a.y+b.y);
	}
	friend Point operator -(Point a,Point b)
	{
		return Point(a.x-b.x,a.y-b.y);
	}
	friend Point operator *(ld a,Point b)
	{
		return Point(a*b.x,a*b.y);
	}
	friend ld operator *(Point a,Point b)
	{
		return a.x*b.x+a.y*b.y;
	}
	friend ld operator ^(Point a,Point b)
	{
		return a.x*b.y-a.y*b.x;
	}
}a[N][3],Poi[N*N];
struct Line
{
	Point p,v;
	Line(){}
	Line(Point _,Point __){p=_,v=__-_;}
	Point operator [](int k)
	{
		if(k)	return p+v;
		else	return p;
	}
	friend bool Cross(Line a,Line b)
	{
		return (a.v^b[0]-a.p)*(a.v^b[1]-a.p)<-EPS&&(b.v^a[0]-b.p)*(b.v^a[1]-b.p)<-EPS;
	}
	friend Point getP(Line a,Line b)
	{
		Point u=a.p-b.p;
		ld temp=(b.v^u)/(a.v^b.v);
		return a.p+temp*a.v;
	}
}l[N][3],T;
pr p[N];
int main()
{
	int n,m,i,j,k,x,y,cnt,tot;
	ld ans,last,A,B,sum;
	scanf("%d",&n);
	for(i=1,tot=0;i<=n;i++)
	{
		a[i][0].read(),a[i][1].read(),a[i][2].read();
		Poi[++tot]=a[i][0],Poi[++tot]=a[i][1],Poi[++tot]=a[i][2];
		sort(a[i],a[i]+3);
		if((a[i][2]-a[i][0]^a[i][1]-a[i][0])>EPS)
			l[i][0]=Line(a[i][0],a[i][2]),l[i][1]=Line(a[i][2],a[i][1]),l[i][2]=Line(a[i][1],a[i][0]);
		else
			l[i][0]=Line(a[i][2],a[i][0]),l[i][1]=Line(a[i][1],a[i][2]),l[i][2]=Line(a[i][0],a[i][1]);
	}
	for(i=1;i<=n;i++)
	{
		for(j=1;j<i;j++)
		{
			for(x=0;x<3;x++)
				for(y=0;y<3;y++)
				{
					if(Cross(l[i][x],l[j][y]))
						Poi[++tot]=getP(l[i][x],l[j][y]);
				}
		}
	}
	sort(Poi+1,Poi+tot+1);
	ans=0,last=Poi[1].x;
	T=Line(Point(0,-INF),Point(0,INF));
	for(i=2;i<=tot;i++)
	{
		T.p.x=(last+Poi[i].x)/2;
		for(j=1,cnt=0;j<=n;j++)
		{
			if(Cross(l[j][0],T))
			{
				A=getP(l[j][0],T).y;
				if(Cross(l[j][1],T))
					B=getP(l[j][1],T).y;
				else
					B=getP(l[j][2],T).y;
				if(A>B)	swap(A,B);
				p[++cnt]=pr(A,B);
			}
		}
		sort(p+1,p+cnt+1);
		for(j=1,sum=0,A=-INF;j<=cnt;j++)
		{
			if(p[j].first>A)
			{
				sum+=p[j].second-p[j].first;
				A=p[j].second;
			}
			else
			{
				if(p[j].second>A)
					sum+=p[j].second-A,A=p[j].second;
			}
		}
		ans+=(Poi[i].x-last)*sum;
		last=Poi[i].x;
	}
	printf("%.2lf\n",(double)ans);
	return 0;
}
时间: 2024-08-26 01:57:35

bzoj-1845 三角形面积并的相关文章

BZOJ 1845: [Cqoi2005] 三角形面积并 [计算几何 扫描线]

1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1151  Solved: 313[Submit][Status][Discuss] Description 给出n个三角形,求它们并的面积. Input 第一行为n(N < = 100), 即三角形的个数 以下n行,每行6个整数x1, y1, x2, y2, x3, y3,代表三角形的顶点坐标.坐标均为不超过10 ^ 6的实数,输入数据保留1位小数 Out

bzoj 1845: [Cqoi2005] 三角形面积并 扫描线

1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 848  Solved: 206[Submit][Status][Discuss] Description 给出n个三角形,求它们并的面积. Input 第一行为n(N < = 100), 即三角形的个数 以下n行,每行6个整数x1, y1, x2, y2, x3, y3,代表三角形的顶点坐标.坐标均为不超过10 ^ 6的实数,输入数据保留1位小数 Outp

BZOJ 1845 CQOI 2005 三角形面积并 扫描线

题目大意:给出一些三角形,求这些三角形面积的并. 思路:应该可以辛普森积分,但是应该会很麻烦.. 以前扫描线就写过矩形的用数据结构维护的那种,和计算几何不占边,这次才是好好写了一次正宗的扫描线.不得不说这个算法还是很靠谱的. 其实这个思路不仅限于三角形面积的并,所有凸多边形的面积并应该都可以解决. 对于任意由线段组成的图形,对这个图形进行多次的划分,总可以将这个图形划分成梯形,面积也很好计算.那么按照什么划分呢?将所有三角形的边都求交点,不难发现,以这些点为划分依据的话,相邻两点之间一定是一个或

BZOJ1845CQOI2005三角形面积并

1845: [Cqoi2005] 三角形面积并 Description 给出n个三角形,求它们并的面积. Input 第一行为n(N < = 100), 即三角形的个数 以下n行,每行6个整数x1, y1, x2, y2, x3, y3,代表三角形的顶点坐标.坐标均为不超过10 ^ 6的实数,输入数据保留1位小数 Output 输出并的面积u, 保留两位小数 Sample Input 2 0.0 0.0 2.0 0.0 1.0 1.0 1.0 0.0 3.0 0.0 2.0 1.0 Sample

叉乘、快速排斥与跨立实验及求取三角形面积

<pre name="code" class="cpp">叉乘 (一)判断方向 (二)判断线段相交 (三)求三角形面积 (一)判断方向 叉乘的性质如下: (1). P x Q > 0; 表示P在Q的顺时针方向; (2). p x Q < 0; 表示P在Q的逆时针方向; (3). P x Q = 0; 表示P和Q是共线的 P(x1,y1),Q(x2,y2), P*Q=x1y2-x2y1 判断结果三种状态 模版为: struct point {

三角形面积

如图1所示.图中的所有小方格面积都是1. 那么,图中的三角形面积应该是多少呢? 请填写三角形的面积.不要填写任何多余内容或说明性文字.

三角形面积(海伦公式)

来自:http://www.oschina.net/code/snippet_149523_14180 描述 给你三个点,表示一个三角形的三个顶点,现你的任务是求出该三角形的面积 输入 每行是一组测试数据,有6个整数x1,y1,x2,y2,x3,y3分别表示三个点的横纵坐标.(坐标值都在0到10000之间)输入0 0 0 0 0 0表示输入结束测试数据不超过10000组 输出 输出这三个点所代表的三角形的面积,结果精确到小数点后1位(即使是整数也要输出一位小数位) 样例输入 0 0 1 1 1

rwkj 1363 正方形 长方形 三角形面积

C++:重载函数2(计算面积)时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte总提交:370 测试通过:241 描述 定义重载函数area(),分别计算正方形.长方形和三角形的面积. 输入 共计有3行. 第1行有一个实数,为正方形的边长: 第2行有二个实数,为长方形的两条边长: 第3行有三个实数,为三角形的三边长. 输出 正方形.长方形和三角形的面积(保留3位小数). 样例输入 3.54.2 5.623.0 4.0 5.0 样例输出 12.25023.6

Java入门:基础算法之计算三角形面积

本部分介绍如何计算三角形面积. /** * @author: 理工云课堂 * @description: 程序计算三角形的面积.三角形的底和高由用户输入 */ import java.util.Scanner; class AreaTriangleDemo { public static void main(String args[]) { Scanner scanner = new Scanner(System.in); System.out.println("Enter the width

nyist 67三角形面积

三角形面积时间限制:3000 ms | 内存限制:65535 KB 难度:2描述 给你三个点,表示一个三角形的三个顶点,现你的任务是求出该三角形的面积输入每行是一组测试数据,有6个整数x1,y1,x2,y2,x3,y3分别表示三个点的横纵坐标.(坐标值都在0到10000之间)输入0 0 0 0 0 0表示输入结束测试数据不超过10000组输出输出这三个点所代表的三角形的面积,结果精确到小数点后1位(即使是整数也要输出一位小数位)样例输入0 0 1 1 1 30 1 1 0 0 00 0 0 0