hiho一下 第140周 清理海报

时间限制:5000ms 单点时限:1000ms 内存限制:256MB

描述

小Hi实验室所在的建筑一楼有一个用于贴海报的黑板,不停的有新的海报往上贴,也会安排人员不断的对海报进行清理,而最近,轮到了小Hi去对海报进行清理。

黑板是一块W*H大小的区域,如果以左下角为直角坐标系的话,在上次清理后第i张贴上去的海报可以视作左下角为(X1i, Y1i),右上角为(X2i, Y2i)的一个矩形。

撕去一张海报会导致所有覆盖在其上的海报都被同时撕掉(这样被称为连带,这个过程是具有传递性的,即如果A覆盖B,B覆盖C,那么撕掉C会导致A和B均被撕掉),但是一张海报想要被手动撕掉的话需要至少存在一个角没有被其他海报覆盖(海报A被海报B覆盖当且仅当他们存在面积大于0的交集并且A在B之前贴出,海报A的一个角被海报B覆盖当且仅当这个顶点处于海报B的内部)。

于是现在问题来了,为了节约时间,小Hi决定一次性撕掉尽可能多的海报,那么他应该选择哪张海报呢?在效果相同的情况下,小Hi倾向于选择更早贴出的海报。

输入

每个输入文件仅包含单组测试数据。

每组测试数据的第一行为三个正整数W,H和N,分别表示黑板的宽、高以及目前张贴出的海报数量。

接下来的N行,每行为四个正整数X1i、Y1i、X2i和Y2i,描述第i张贴出的海报。

对于20%的数据,满足1<=N<=5,1<=W,H<=10

对于100%的数据,满足1<=N<=1000,0<=X1i, X2i <= W, 0<=Y1i, Y2i<=H, 1<=W,H<=108

输出

对于每组测试数据,输出两个正整数Ans和K,表示小Hi一次最多能撕掉多少张海报,和他选择的海报是第几张贴出的。

样例输入
6 7 4
0 0 4 4
1 0 3 4
1 4 4 6
0 0 3 5


样例输出

3 1

#include <iostream>
#include <algorithm>
#include <cstring>
#include <bitset>

using namespace std;

struct Rect
{
	int x1, y1, x2, y2;
	void set( int _x1, int _y1, int _x2, int _y2 )
	{
		x1 = _x1;
		x2 = _x2;
		y1 = _y1;
		y2 = _y2;
	}
};

int W, H, N;
const int maxn = 1005;
Rect paper[maxn];
bitset<maxn> cover[maxn];
int ans[maxn];

bool JudgeCover( int i, int j )
{
	Rect rect1;
	rect1.x1 = max( paper[i].x1 , paper[j].x1 );
	rect1.y1 = max( paper[i].y1 , paper[j].y1 );
	rect1.x2 = min( paper[i].x2 , paper[j].x2 );
	rect1.y2 = min( paper[i].y2 , paper[j].y2 );
	if ( rect1.x1 < rect1.x2 && rect1.y1 < rect1.y2 )
	{
		return true;
	}
	else
		return false;
}

void JudgeWhichCover( int i, int j, bool &lefttop, bool &leftbottom, bool &righttop, bool &rightbottom )
{
	if( !JudgeCover( i, j))
	{
		return;
	}
	if( paper[i].x1 > paper[j].x1 && paper[i].x1 < paper[j].x2 && paper[i].y1 > paper[j].y1 && paper[i].y1 < paper[j].y2)
	{
		leftbottom = true;
	}
	if( paper[i].x1 > paper[j].x1 && paper[i].x1 < paper[j].x2 && paper[i].y2 > paper[j].y1 && paper[i].y2 < paper[j]
			                                                                                                         .y2)
	{
		lefttop = true;
	}
	if( paper[i].x2 > paper[j].x1 && paper[i].x2 < paper[j].x2 && paper[i].y2 > paper[j].y1 && paper[i].y2 < paper[j].y2)
	{
		righttop = true;
	}
	if( paper[i].y1 > paper[j].y1 && paper[i].y1 < paper[j].y2 && paper[i].x2 > paper[j].x1 && paper[i].x2 < paper[j].x2)
	{
		rightbottom = true;
	}
}
int main()
{
	freopen("/home/liyuanshuo/ClionPRoject/hihocoder/in.in", "r" , stdin );
	cin>>W>>H>>N;
	for (int i = 1 ; i <= N ; ++i)
	{
		cin>>paper[i].x1>>paper[i].y1>>paper[i].x2>>paper[i].y2;
		//scanf("%d%d%d%d", &paper[i].x1, &paper[i].y1, &paper[i].x2, &paper[i].y2);
	}
	for (int i = N - 1 ; i >= 1 ; i-- )
	{
		cover[i][i] = 1;
		for (int j = N ; j > i  ; --j)
		{
			if( JudgeCover(i, j) )
			{
				cover[i][j] = 1;
				cover[i] |= cover[j];
			}
		}
	}
	cover[N][N] = 1;
	
	memset( ans, 0, sizeof(ans) );
	for (int i = 1 ; i <= N - 1  ; ++i)
	{
		int tmp = 1;
		bool lefttop = false;
		bool leftbottom = false;
		bool righttop = false;
		bool  rightbottom = false;
		for ( int j = i ; j <= N ; j++ )
		{
			if ( cover[i][j] )
			{
				JudgeWhichCover(i, j, lefttop, leftbottom, righttop, rightbottom );
				if ( lefttop && leftbottom && righttop && rightbottom )
				{
					ans[i] = 0;
					break;
				}
				ans[i]++;
			}
		}
	}
	ans[N] = 1;
	int answer = ans[1], k = 1;
	
	for (int i = 2 ; i <= N ; ++i)
	{
		if( answer < ans[i] )
		{
			answer = ans[i];
			k = i;
		}
	}
	cout<<answer<<" "<<k<<endl;
	//std::cout << "Hello, World!" << std::endl;
	return 0;
}