题目:http://poj.org/problem?id=1177题意:墙上贴着一些海报、照片等矩形,所有的边都为垂直或水平。每个矩形可以被其它矩形部分或完全遮盖,所有矩形合并成区域的边界周长称为轮廓周长。思路:见陈宏论文//一维数组 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int maxn=10000; const int inf=10010; struct Point { int lx, ly, rx, ry; }p[maxn+10]; int x[maxn+10], y[maxn+10], z[maxn+10], len_x, len_y; int n, a, b, c, d; int cmpx(Point a, Point b) { if (a.lx<b.lx) return 1; else return 0; } int cmpy(Point a, Point b) { if (a.ly<b.ly) return 1; else return 0; } int cmp(int a, int b) { if (a<b) return 1; else return 0; } int rowlen() { sort(x, x+len_x, cmp); sort(p, p+n, cmpy); int up, down; int res=0; for (int i=1; i<len_x; i++) { if (abs(x[i]-x[i-1])==0) continue; up=down=-inf; for (int j=0; j<n; j++) { if (x[i-1]-p[j].lx>=0&&x[i]-p[j].rx<=0) { if (p[j].ly-up>0) { //printf("%d %d\n", x[i], x[i-1]); res+=2*(x[i]-x[i-1]); //printf("res=%d\n", res); down=p[j].ly, up=p[j].ry; } else if (p[j].ry-up>0) up=p[j].ry; } } } return res; } int collen() { sort(y, y+len_y, cmp); sort(p, p+n, cmpx); int up, down; int res=0; for (int i=1; i<len_y; i++) { if (abs(y[i]-y[i-1])==0) continue; up=down=-inf; for (int j=0; j<n; j++) { if (y[i-1]-p[j].ly>=0&&y[i]-p[j].ry<=0) { if (p[j].lx-up>0) { //printf("%d %d\n", x[i], x[i-1]); res+=2*(y[i]-y[i-1]); //printf("res=%d\n", res); down=p[j].lx, up=p[j].rx; } else if (p[j].rx-up>0) up=p[j].rx; } } } return res; } int main() { //freopen("in.txt", "r", stdin); while (scanf("%d", &n)==1) { len_x=len_y=0; for (int i=0; i<n; i++) { scanf("%d %d %d %d", &p[i].lx, &p[i].ly, &p[i].rx, &p[i].ry); x[len_x++]=p[i].lx, x[len_x++]=p[i].rx; y[len_y++]=p[i].ly, y[len_y++]=p[i].ry; } int ans=0; ans+=rowlen(); ans+=collen(); printf("%d\n", ans); } return 0; }//线段树 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; const int maxn=10000; struct STree { int l, r; int len, segnum, cover, sum, lcover, rcover; }st[maxn*4]; struct Line { int y_top, y_btm; int x; int in; bool operator<(Line l) const { return x<l.x; } }line[maxn+10]; int n, cnt, y[maxn+10]; void BuildTree(int l, int r, int i) { st[i].l=l, st[i].r=r; st[i].len=y[r]-y[l]; st[i].segnum=st[i].cover=st[i].sum=st[i].lcover=st[i].rcover=0; if (r-l>1) { int mid=(l+r)>>1; BuildTree(l, mid, i*2); BuildTree(mid, r, i*2+1); } } void GetLen(int x) { if (st[x].cover>0) st[x].sum=st[x].len; else if (st[x].r-st[x].l>1) st[x].sum=st[x*2].sum+st[x*2+1].sum; else st[x].sum=0; } void GetSegNum(int x) { if (st[x].cover>0) { st[x].lcover=st[x].rcover=1; st[x].segnum=1; } else if (st[x].r-st[x].l>1) { st[x].lcover=st[x*2].lcover; st[x].rcover=st[x*2+1].rcover; st[x].segnum=st[x*2].segnum+st[x*2+1].segnum-st[x*2].rcover*st[x*2+1].lcover; } else { st[x].lcover=st[x].rcover=0; st[x].segnum=0; } } void Insert(int l, int r, int i) { if (st[i].l==l&&st[i].r==r) st[i].cover++; else { int mid=(st[i].l+st[i].r)>>1; if (r<=mid) Insert(l, r, 2*i); else if (l>=mid) Insert(l, r, 2*i+1); else { Insert(l, mid, 2*i); Insert(mid, r, 2*i+1); } } GetLen(i); GetSegNum(i); } void Delete(int l, int r, int i) { if (st[i].l==l&&st[i].r==r) st[i].cover--; else { int mid=(st[i].l+st[i].r)>>1; if (r<=mid) Delete(l, r, i*2); else if (l>=mid) Delete(l, r, i*2+1); else { Delete(l, mid, 2*i); Delete(mid, r, 2*i+1); } } GetLen(i); GetSegNum(i); } int GetIndex(int x) { return lower_bound(y, y+cnt, x)-y; } int main() { //freopen("in.txt", "r", stdin); while (scanf("%d", &n)==1) { int x1, y1, x2, y2; for (int i=0; i<n; i++) { scanf("%d %d %d %d", &x1, &y1, &x2, &y2); line[i*2].x=x1, line[i*2+1].x=x2; line[i*2].y_top=line[i*2+1].y_top=y1; line[i*2].y_btm=line[i*2+1].y_btm=y2; line[i*2].in=1, line[i*2+1].in=0; y[i*2]=y1, y[i*2+1]=y2; } sort(y, y+2*n); sort(line, line+2*n); cnt=0; for (int i=1; i<2*n; i++) { if (y[i]!=y[i-1]) y[cnt++]=y[i-1]; } y[cnt++]=y[2*n-1]; BuildTree(0, cnt-1, 1); int ans=0; int last_num=0; for (int i=0; i<2*n-1; i++) { if (line[i].in) Insert(GetIndex(line[i].y_top), GetIndex(line[i].y_btm), 1); else Delete(GetIndex(line[i].y_top), GetIndex(line[i].y_btm), 1); ans+=st[1].segnum*(line[i+1].x-line[i].x)*2; ans+=abs(st[1].sum-last_num); last_num=st[1].sum; } Delete(GetIndex(line[2*n-1].y_top), GetIndex(line[2*n-1].y_btm), 1); ans+=abs(st[1].sum-last_num); printf("%d\n", ans); } return 0; }
PKU 1177 Picture
最新推荐文章于 2013-03-31 20:03:33 发布
本文介绍了一种计算多个矩形重叠后的轮廓周长的方法,通过一维数组和线段树两种方式实现,适用于解决计算机图形学中计算复杂形状周长的问题。

1052

被折叠的 条评论
为什么被折叠?



