一道很有意思的题目。只是今天的课程比较紧张,中午敲了下题,下午上完课后接着敲了下题。改了些bug,终于还是过了。鼓励一下~
解题思路:
题目大意是矩形覆盖问题,求最终见到的各种颜色矩形的面积。由于矩形比较多1000个而且坐标范围用点阵表示会爆空间。题中给的Hints也是含混不清。在队友提点下,终于到了解决的办法。用递归,因为题中有很明显的子问题性质,当前色块的矩形被上面的矩形覆盖之后可以分割成小矩形,再通过小矩形被更上面的矩形覆盖后进而递推。
由于没有想出用好的方法来表示矩形的碰撞情况,若用枚举的话,考虑情况太多而且代码冗余量太大。
矩形覆盖有3种情况:
1.完全不相交:
2.部分相交:
1.>1个角覆盖;
2.>2个角覆盖;
3.完全被包含(4个角覆盖):
显然枚举太麻烦!!!
考虑一般情况:
这样蓝色矩形就在黄色矩形的切割下分为4个小矩形。
把4个小矩形的坐标定义好,再进行递归。
那么其他情况怎么办呢??
同样的在这种情况下,也分为4个小矩形,明显的S1和S4是不符合条件的。
通过我们的坐标定义可以看出S1.ury<S1.lly 这样明显的翻折过来了,这样的矩形不能用。
而S4.urx<S4.llx,同样这样的矩形也不能用。
这种表达方式把所有的情况都包含在内了?还缺了一种:完全相交的情况!
通过坐标定义可以切出符合题意的矩形。将这种情况滤除掉就好了。
另外细节方面要注意的就是细心,还有就是坐标的问题。urx和ury那个点时没有实心点的。这点要好好注意。
总算是切掉了!
Code:
/*
ID:13ysen
LANG:C++
PROG:rect1
*/
#include<stdio.h>
#include<algorithm>
#define MAXR 1001
using namespace std;
struct node
{
int llx,lly,urx,ury;
}rect[MAXR];
struct Color
{
int color;
int cnt;
}rec[MAXR];
bool cmp( Color a,Color b ){ return a.color<b.color; }
int N;
int min( int a,int b ){ return a<b?a:b; }
int max( int a,int b ){ return a>b?a:b; }
bool judge( node a )
{
if( a.llx>a.urx || a.lly>a.ury )
return false;
return true;
}
void recursion( node a,int layer,int index )
{
if( judge(a)==false )
return ;
bool recur=false;
for( int i=layer+1;i<=N;i++ )
{
if( a.llx>rect[i].urx || a.lly>rect[i].ury || a.urx<rect[i].llx || a.ury<rect[i].lly )
continue;
recur=true;
node s1,s2,s3,s4;
s1=s2=s3=s4=a;
s1.lly=rect[i].ury+1;
s3.ury=rect[i].lly-1;
s2.urx=rect[i].llx-1;
s4.llx=rect[i].urx+1;
s4.lly=s2.lly=max( rect[i].lly,a.lly );
s4.ury=s2.ury=min( rect[i].ury,a.ury );
recursion( s1,i,index );
recursion( s2,i,index );
recursion( s3,i,index );
recursion( s4,i,index );
break;
}
if( recur==false )
rec[index].cnt+=(a.urx-a.llx+1)*(a.ury-a.lly+1);
return ;
}
int main()
{
freopen( "rect1.in","r",stdin );
freopen( "rect1.out","w",stdout );
int A,B;
scanf( "%d %d %d",&A,&B,&N );
for( int i=0;i<=N;i++ )
rec[i].cnt=rec[i].color=0;
rect[0].llx=rect[0].lly=0;
rect[0].urx=A-1;rect[0].ury=B-1;
rec[0].color=1;
for( int i=1;i<=N;i++ )
{
scanf( "%d %d %d %d %d",&rect[i].llx,&rect[i].lly,&rect[i].urx,&rect[i].ury,&rec[i].color );
rect[i].urx-=1;
rect[i].ury-=1;
}
for( int i=0;i<=N;i++ )
recursion( rect[i],i,i );
sort( rec,rec+N+1,cmp );
int ans=0;
for( int i=0;i<=N;i++ )
{
if( rec[i].color==rec[i+1].color )
ans+=rec[i].cnt;
else
{
if( rec[i].cnt+ans>0 )
printf( "%d %d\n",rec[i].color,rec[i].cnt+ans );
ans=0;
}
}
return 0;
}