您的位置:首页 > 其它

算法学习之——矩形切割思想

2014-11-19 13:17 246 查看
算法学习之——矩形切割思想
MPS
【定义 Define】
对于求解若干个矩形的面积的交集,而且又必须是O(NlogN)以内的,往往采用矩形切割思想
说白了,其实就是给你若干个矩形,让你求任意一个矩形不被覆盖的面积总和
【处理方法】
类似下图:(图片出处:http://www.cppblog.com/xiongnanbin/articles/90805.html?opt=admin)



我们假设有2个矩形:A和B,A用白色染色,B用黄色染色,A放在底层,B放在A之上,这样,黄色区域就是矩形A和矩形B的交集了,我们可以发现
wx1=max(wx1,x1)
wx2=min(wx2,x2)
wy1=max(wy1,y1)
wy2=min(wy2,y2)
这样,我们判断是否存在,不存在则没有,结束,否则继续上浮,寻找下一个重叠矩阵
【例题】
(转载自:USACO)

Shaping Regions
形成的区域

译 by tim green

  N个不同的颜色的不透明的长方形(1 <= N <= 1000)被放置在一张宽为A长为B的白纸上。

这些长方形被放置时,保证了它们的边于白纸的边缘平行。

所有的长方形都放置在白纸内,所以我们会看到不同形状的各种颜色。

坐标系统的原点(0,0)设在这张白纸的左下角,而坐标轴则平行于边缘。

PROGRAM NAME: rect1

INPUT FORMAT

每行输入的是放置长方形的方法。

第一行输入的是那个放在底的长方形(即白纸)。

第 1 行:A , B 和 N, 由空格分开 (1 <=A, B<=10,000)
第 2 到N+1行:为五个整数 llx, lly, urx, ury, color 这是一个长方形的左下角坐标,右上角坐标和颜色(1<=color<=2500)。

颜色 1和底部白纸的颜色相同。
SAMPLE INPUT (file rect1.in)

20 20 3

2 2 18 18 2

0 8 19 19 3

8 0 10 19 4

OUTPUT FORMAT

输出文件应该包含一个所有能被看到颜色连同该颜色的总面积的清单( 即使颜色的区域不是连续的),按color的增序顺序。

不要显示没有区域的颜色。

SAMPLE OUTPUT (file rect1.out)

1 91

2 84

3 187

4 38

这题网上有三种做法,第一种是二维线段树(难度太高,空间不足,忽略)第二种是矩形树(忽略)第三种就是矩形切割算法

我们同样染色(题目要求),然后直接就交集即可

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <deque>
using namespace std;

const int MaxN=10001;
const int MAXN=2500;

int x1[MaxN],y1[MaxN],x2[MaxN],y2[MaxN],n,m,c;
int color[MaxN],area[MaxN];
int now;//当前矩形的颜色

//矩形切割思想

void solve(int l,int r,int b,int t,int z){
while(z<=c && (l>=x2[z] || r<=x1[z] || b>=y2[z] || t<=y1[z]))z++;
if(z>c){//没有重叠
area[now]+=(r-l)*(t-b);
return;
}
if(l<x1[z])//右上角重叠
{
solve(l,x1[z],b,t,z+1);
l=x1[z];
}
if(r>x2[z]){
solve(x2[z],r,b,t,z+1);
r=x2[z];
}
if(b<y1[z])solve(l,r,b,y1[z],z+1);
if(t>y2[z])solve(l,r,y2[z],t,z+1);
}

int main(){
scanf("%d%d%d",&n,&m,&c);
int i;
x1[0]=y1[0]=0;x2[0]=n;y2[0]=m;color[0]=1;
for(i=1;i<=c;i++)scanf("%d%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i],&color[i]);
memset(area,0,sizeof(area));
for(i=c;i>=0;i--){
now=color[i];
solve(x1[i],x2[i],y1[i],y2[i],i+1);
}
for(i=1;i<=MAXN;i++)
if(area[i])printf("%d %d\n",i,area[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: