poj1177--Picture--扫描线

2024-06-12 12:18
文章标签 扫描线 picture poj1177

本文主要是介绍poj1177--Picture--扫描线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

思想和前段时间的1151差不多,


都是通过扫描线的移动来计算周长,不同的是要通过对与x轴平行的扫描线扫一次,与y轴平行的扫描线扫一次,


扫描两次得到周长。


变量last为记录上一次扫描得到的长度,sum为记录这一次总共扫描得到的长度。


abs(sum-last)即为所扫描到的一次长度,


非常耐人寻味的是,我询问学长为什么可以这样做的时候,学长提到了一个投影的概念,即投影的变化反应长度的变化,


智商拙计。。。。还在思考ing。


据说这道题还可以通过一次扫描顺带扫描y轴得到周长(记录x轴上分割开来的即不连续线段个数,乘以2就是y的个数。PS:这个有种特殊情况不满足,即一个矩形包含一个小矩形的情况),改天再碰扫描线的时候再来看看吧。


一下是代码:可与poj1151比较,是我的代码风格= =!


#include <cstdio>
#include <algorithm>
using namespace std;
const int maxnum=10010;typedef struct
{int l,r;int ll,rr;int cover;int len;
}Nodex;typedef struct
{int h,d;int hh,dd;int cover;int len;
}Nodey;typedef struct
{int flag; //记录出边还是入边,入边为1,出边为-1.int x1,x2,y;
}scanlen_x;typedef struct
{int flag; //记录出边还是入边,入边为1,出边为-1int y1,y2,x;
}scanlen_y;Nodex treex[maxnum*4];
Nodey treey[maxnum*4];
scanlen_x scanx[maxnum];
scanlen_y scany[maxnum];
int x[maxnum];
int y[maxnum];bool mycomparex(scanlen_x a,scanlen_x b)
{return a.y<b.y;
}bool mycomparey(scanlen_y a,scanlen_y b)
{return a.x<b.x;
}void buildx(int root,int l,int r)
{treex[root].l=l;treex[root].r=r;treex[root].ll=x[l];treex[root].rr=x[r];treex[root].cover=0;treex[root].len=0;if(l+1==r) return;int mid=(l+r)>>1;buildx(root<<1,l,mid);buildx(root<<1|1,mid,r);
}void buildy(int root,int l,int r)
{treey[root].d=l;treey[root].h=r;treey[root].dd=y[l];treey[root].hh=y[r];treey[root].cover=0;treey[root].len=0;if(l+1==r) return;int mid=(l+r)>>1;buildy(root<<1,l,mid);buildy(root<<1|1,mid,r);
}void updatex(scanlen_x a,int l,int r,int root)
{if(l==treex[root].ll&&r==treex[root].rr)treex[root].cover+=a.flag;else{int mid=(treex[root].l+treex[root].r)>>1;if(l>=x[mid]) updatex(a,l,r,root<<1|1);else if(r<=x[mid]) updatex(a,l,r,root<<1);else{updatex(a,l,x[mid],root<<1);updatex(a,x[mid],r,root<<1|1);}}if(treex[root].cover)//以下更新root的len,即扫描到的总长度treex[root].len=treex[root].rr-treex[root].ll;else if(treex[root].l+1==treex[root].r)treex[root].len=0;elsetreex[root].len=treex[root<<1].len+treex[root<<1|1].len;
}
void updatey(scanlen_y a,int d,int h,int root)
{if(d==treey[root].dd&&h==treey[root].hh)treey[root].cover+=a.flag;else{int mid=(treey[root].d+treey[root].h)>>1;if(d>=y[mid]) updatey(a,d,h,root<<1|1);else if(h<=y[mid]) updatey(a,d,h,root<<1);else{updatey(a,d,y[mid],root<<1);updatey(a,y[mid],h,root<<1|1);}}//以下更新root的len,即扫描到的总长度.if(treey[root].cover)treey[root].len=treey[root].hh-treey[root].dd;else if(treey[root].d+1==treey[root].h)treey[root].len=0;elsetreey[root].len=treey[root<<1].len+treey[root<<1|1].len;
}
int main()
{int n;while(scanf("%d",&n)==1){int i,m=1,k=1;for(i=1;i<=n;++i){int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);scanx[m].x1=x1;scanx[m].x2=x2;scanx[m].y=y1;scanx[m].flag=1;x[m++]=x1;scanx[m].x1=x1;scanx[m].x2=x2;scanx[m].y=y2;scanx[m].flag=-1;x[m++]=x2;scany[k].y1=y1;scany[k].y2=y2;scany[k].x=x1;scany[k].flag=1;y[k++]=y1;scany[k].y1=y1;scany[k].y2=y2;scany[k].x=x2;scany[k].flag=-1;y[k++]=y2;}--m,--k;sort(scanx+1,scanx+m+1,mycomparex);sort(x+1,x+m+1);sort(scany+1,scany+k+1,mycomparey);sort(y+1,y+k+1);int o=2,p=2;for(i=2;i<=m;++i)if(x[i]!=x[i-1]) x[o++]=x[i];for(i=2;i<=k;++i)if(y[i]!=y[i-1]) y[p++]=y[i];--o,--p;buildx(1,1,o);//在x轴建立线段树buildy(1,1,p);//在y轴建立线段树int ans=0,last=0;for(i=1;i<=m;++i){updatex(scanx[i],scanx[i].x1,scanx[i].x2,1);ans+=abs(treex[1].len-last);last=treex[1].len;}last=0;for(i=1;i<=k;++i){updatey(scany[i],scany[i].y1,scany[i].y2,1);ans+=abs(treey[1].len-last);last=treey[1].len;}printf("%d\n",ans);}return 0;
}




这篇关于poj1177--Picture--扫描线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1054188

相关文章

FZU 2187 扫描线

和HDU 1255差不多 这次是求只被覆盖一次的矩形面积和 修改callen函数即可 data[k].len表示被覆盖的纵长度 data[k].key表示被只被覆盖一次的纵长度 #include "stdio.h"#include "string.h"#include "stdlib.h"#include "math.h"#include "iostream"#inc

HDU 1255 扫描线

扫描线处理矩形覆盖过至少两次的区域的面积. 把callen函数的修改一下即可 data[k].len表示被覆盖的长度 data[k].sum表示被覆盖两次以上的长度 #include "stdio.h"#include "string.h"#include "algorithm"#include "math.h"using namespace std;struct Mar

Hud 1162 Eddy's picture[MST(kruscal)]

题目链接:点击打开链接 还是很基础的最小生成树 #include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int N=105;const int Max=5005;int n,top,father[N];struct Point{double x,y;}point[N];str

MFC 在picture控件中,嵌入一个对话框

一、对话框中显示对话框的方法: 1、首先创建要在对话框里显示的那个对话框,命名为:IDD_INNER。 设置这个对话框的属性: 1)、“Style”选择“Child”;中文版“样式”选择“下层”。 2)、“Border”为“None”;中文版“边框”选择“无”。   2、为了显示时能够准确定位,我们可以在右边要显示对话框的地方放入一个Pic控件,命名为:IDC_STATIC_RECT,Visibl

【TB作品】MSP430F5529,单片机,Picture to pixels,乌鸦喝水OLED

功能 Picture to pixels. Use bitmaps to tell a story. Convert pictures to bitmaps and store the bitmaps in a header file. In the main program, draw the pictures on the OLED screen in sequence to tell a

Halcon10 与 VC++交互,通过picture control显示图像

vs2010运行通过。VC++做的。 这个程序大概时这样的,左边是一个picture control,点击识别,通过调用halcon读图片,显示在vc++的mfc的picture control控件上。 步骤: 1》》》》》》》》》》》》》》》》》》 添加halcon头文件 2》》》》》》》》》》》》》》》》》》 添加一些类库 3》

P5490.扫描线(python)

这个洛谷怎么对于python不太友好呢,没几次能全过的 本题使用扫描线的模板,首先把所有x坐标排序去重,放进列表X中。把所有横线lines排序。这样把所有矩阵都分成了块。对于每一块,高=lines[i+1]-lines[i],宽就等于在这一块中,每个矩阵的并。 比如说图中,纵坐标在3-5之间,那么高度就是2,其中有两块矩阵并起来,计算并起来的宽度=80-10=70,高×宽就是这一块的面积。

CSU 1335: 高桥和低桥(扫描线) 13年省赛题

1335: 高桥和低桥 Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 957   Solved: 279 [ Submit][ Status][ Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪

扫描线 窗内的星星

题目链接:248. 窗内的星星 算法分析 经过亚特兰蒂斯 那题的洗礼,这道扫描线题目就显得简单多了。但是很多细节还是得注意。这里只说细节。 1.边框上的星星不算怎么处理。如下图: 左下角的星星坐标为 ( x , y ) (x,y) (x,y),如果边框上的星星算的话,那么整个蓝色区域都可以放置边框的右上角顶点。如果不算的话,因为星星的坐标都是整数,边框的宽高也是整数,所以可放置的区域范围

扫描线 亚特兰蒂斯

题目链接:247. 亚特兰蒂斯 算法分析 只说细节。 这道题目不是特别严格的线段树,因为线段树维护的信息具有区间可合并性,这道题目想了很久想不出可以区间直接合并的信息。我们在这里维护的是离散化后表示小段的数组,设为 a [ ] a[] a[]吧,对于一个边界的两个纵坐标,设为 y 1 y1 y1和 y 2 y2 y2,离散化后的结果为 [ a l , a r ] [al,ar] [al,ar