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