HDU1542&&POJ1151-Atlantis
来源:互联网 发布:java 自定义函数 编辑:程序博客网 时间:2024/05/17 01:49
Atlantis
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11332 Accepted Submission(s): 4817
The input file is terminated by a line containing a single 0. Don’t process it.
Output a blank line after each test case.
210 10 20 2015 15 25 25.50
Test case #1Total explored area: 180.00
题意:给出n个矩形,形式是左下点和右上点。求它们的面积并。
解题思路:扫描线算法
以下为转载内容,转载地址:http://www.cnblogs.com/fenshen371/p/3214092.html 代码为自己理解后手码
线段树扫描法的题,顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中,这根线很重要。方向的话,可以左右扫,也可以上下扫。方法是一样的,这里我用的是由下向上的扫描法。
如上图所示,坐标系内有两个矩形。位置分别由左下角和右上角顶点的坐标来给出。上下扫描法是对x轴建立线段树,矩形与y平行的两条边是没有用的,在这里直接去掉。如下图。
现想象有一条线从最下面的边开始依次向上扫描。线段树用来维护当前覆盖在x轴上的线段的总长度,初始时总长度为0。用ret来保存矩形面积总和,初始时为0。
由下往上扫描,扫描到矩形的底边时将它插入线段树,扫描到矩形的顶边时将底边从线段树中删除。而在代码中实现的方法就是,每条边都有一个flag变量,底边为1,顶边为-1。
用cover数组(通过线段树维护)来表示某x轴坐标区间内是否有边覆盖,初始时全部为0。插入或删除操作直接让cover[] += flag。当cover[] > 0 时,该区间一定有边覆盖。
开始扫描到第一条线,将它压入线段树,此时覆盖在x轴上的线段的总长度L为10。计算一下它与下一条将被扫描到的边的距离S(即两条线段的纵坐标之差,该例子里此时为3)。
则 ret += L * S. (例子里增量为10*3=30)
结果如下图
橙色区域表示已经计算出的面积。
扫描到第二条边,将它压入线段树,计算出此时覆盖在x轴上的边的总长度。
例子里此时L=15。与下一条将被扫描到的边的距离S=2。 ret += 30。 如下图所示。
绿色区域为第二次面积的增量。
接下来扫描到了下方矩形的顶边,从线段树中删除该矩形的底边,并计算接下来面积的增量。如下图。
蓝色区域为面积的增量。
此时矩形覆盖的总面积已经计算完成。 可以看到,当共有n条底边和顶边时,只需要从下往上扫描n-1条边即可计算出总面积。
============================== 分割线 ========================================
此题因为横坐标包含浮点数,因此先离散化。
#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <algorithm>#include <queue>#include <vector>#include <set>#include <stack>#include <map>#include <climits>using namespace std;#define LL long longconst int maxn=110;struct LINE{ double y,x_l,x_r; int flag; friend bool operator<(LINE a,LINE b) { return a.y<b.y; }}line[2*maxn];struct TREE{ double x_l,x_r; double y; int cover; bool flag;}tree[1000*maxn];int n;double x1,y1,x2,y2;int sum;double x[2*maxn];void build(int k,int l,int r){ tree[k].y=-1; tree[k].cover=0; tree[k].x_l=x[l]; tree[k].x_r=x[r]; tree[k].flag=false; if(l+1==r) { tree[k].flag=true; return; } int mid=(l+r)>>1; build(2*k,l,mid); build(2*k+1,mid,r);}double query(int k,double y,double l,double r,int flag){ if(r<=tree[k].x_l||l>=tree[k].x_r) return 0; if(tree[k].flag) { if(tree[k].cover) { double temp_y=tree[k].y; double ans=(y-temp_y)*(tree[k].x_r-tree[k].x_l); tree[k].y=y; tree[k].cover+=flag; return ans; } else { tree[k].cover+=flag; tree[k].y=y; return 0; } } double ans1,ans2; ans1=query(2*k,y,l,r,flag); ans2=query(2*k+1,y,l,r,flag); return ans1+ans2;}int main(){ int cas=0; while(~scanf("%d",&n)&&n) { sum=1; for(int i=1;i<=n;i++) { scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); x[sum]=x1; line[sum].y=y1; line[sum].x_l=x1; line[sum].x_r=x2; line[sum].flag=1; sum++; x[sum]=x2; line[sum].y=y2; line[sum].x_l=x1; line[sum].x_r=x2; line[sum].flag=-1; sum++; } sort(x+1,x+sum); sort(line+1,line+sum); build(1,1,sum-1); double ans=0; for(int i=1;i<sum;i++) ans+=query(1,line[i].y,line[i].x_l,line[i].x_r,line[i].flag); printf("Test case #%d\nTotal explored area: %.2f\n\n", ++cas,ans); } return 0;}
- HDU1542&&POJ1151-Atlantis
- POJ1151 HDU1542 CODEVS3044 Atlantis 题解&代码
- ZOJ1128 Atlantis(POJ1151/HDU1542 求矩形并)
- poj1151 hdu1542 wikioi3044 Atlantis 矩形面积求并
- poj1151 & hdu1542 Atlantis(扫描线+离散化+线段树)
- 线段树扫描线——HDU1542&&POJ1151-Atlantis
- poj1151 Atlantis
- POJ1151-Atlantis
- poj1151 Atlantis
- poj1151 Atlantis
- hdu1542 Atlantis
- HDU1542--Atlantis
- [HDU1542]Atlantis
- hdu1542----Atlantis
- hdu1542 Atlantis
- hdu1542 Atlantis
- poj1151——Atlantis
- POJ1151 Atlantis [离散化]
- 月入十万:大部分人努力的方向都错了
- Eclipse的简易教程
- AS插件之Gsonformat——自动帮你生成GSON BEAN
- Codeforces Round #326 (Div. 2) D. Duff in Beach
- wampserver 为橙色 可以打开localhost 不能打开phpmyadmin
- HDU1542&&POJ1151-Atlantis
- C语言传值与传值笔记
- 树~java递归实现二叉树先、中、后序遍历
- 解决Python certificate verify failed的问题
- String、StringBuffer与StringBuilder之间区别
- 关于HTTP请求和响应报文格式
- vim实用技巧
- 并查集(递推法)+路径压缩(转)
- Java之数据流DataInput(Output)Stream 和 字节数组流 ByteArrayInput(Output) Stream的嵌套