一道很有意思的题目。只是今天的课程比较紧张,中午敲了下题,下午上完课后接着敲了下题。改了些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; }