[各种面试题] 矩阵覆盖求面积或者周长或者并的面积

首先求覆盖面积有两种方法:

一是先离散化,然后分成 n*m个小格子,然后读入所有矩形,把矩形包含的所有小格子染色,最后统计被染色的格子的面积求和。

二是用线段树+扫描线,很巧的方法,但是别人的代码我没有看懂。

http://blog.csdn.net/dooder_daodao/article/details/6334169

贴一个离散化的代码过来:

注意map[i][j] 表示的是  x[i],y[i], 和x[i+1],y[i+1] 两个点的格子是否被染色。


#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#define M 408
const double eps = 1e-8;
typedef struct{
	double x1,x2,y1,y2;
	void set(double x1,double y1,double x2,double y2)
	{this->x1=x1;this->y1=y1;this->x2=x2;this->y2=y2;}
}Rec;
Rec r[M];
bool map[M][M];
//数组开太小,RE了一次
double x[M],y[M];
int n,nx,ny;
int Cmp(const void *a,const void *b)
{
	return *(double *)a>*(double *)b?1:-1;
}
int Find(double arr[],int low,int up,double v)
{//二分查找,并且一定数组中一定存在与v相等的值
	int mid=(low+up)>>1;
	if(fabs(arr[mid]-v)<eps) return mid;
	if(arr[mid]>v) return Find(arr,low,mid-1,v);
	return Find(arr,mid+1,up,v);
}
int main()
{
	double x1,y1,x2,y2,ans;
	int t=1,i,j,i1,i2,j1,j2,k;
	while(scanf("%d",&n),n){
		for(nx=ny=0,i=0;i<n;i++){
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
			r[i].set(x1,y1,x2,y2);
			x[nx++]=x1;x[nx++]=x2;
			y[ny++]=y1;y[ny++]=y2;
		}
		//排序,进而离散化点
		qsort(x,nx,sizeof(x[0]),Cmp);
		qsort(y,ny,sizeof(y[0]),Cmp);
		//消除相等的值,进行离散化
		for(i=0,j=0;i<nx;i++){
			if(fabs(x[i]-x[j])<eps) continue;
			x[++j]=x[i];
		}nx=j;
		for(i=0,j=0;i<ny;i++){
			if(fabs(y[i]-y[j])<eps) continue;
			y[++j]=y[i];
		}ny=j;
		memset(map,false,sizeof(map));
		for(i=0;i<n;i++){
			i1=Find(x,0,nx,r[i].x1);
			i2=Find(x,0,nx,r[i].x2);
			j1=Find(y,0,ny,r[i].y1);
			j2=Find(y,0,ny,r[i].y2);
			for(j=i1;j<i2;j++){//标记覆盖的区域
				for(k=j1;k<j2;k++)
					map[j][k]=true;
			}
		}
		ans=0.0;
		for(i=0;i<nx;i++){
			for(j=0;j<ny;j++){
				if(map[i][j])
					ans+=(x[i+1]-x[i])*(y[j+1]-y[j]);
			}
		}
		printf("Test case #%d/n",t++);
		printf("Total explored area: ");
		printf("%.2f/n/n",ans);
	}
	return 0;
}


然后求矩形并的面积,那么思路跟上面的离散化是一样的,染色的时候记录被覆盖次数,最后覆盖超过两次的小格子面积统计下就好了。


然后是求周长,方法跟求面积一样,也是两种方法:

一是离散化,然后对每个矩形,把它的四条边都拿下来,然后染色,最后统计被染色的格子就好了。

二还是线段树+扫描线,思路见:

http://www.cnblogs.com/scau20110726/archive/2013/04/13/3018687.html



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值