-
6 7 4 0 0 4 4 1 0 3 4 1 4 4 6 0 0 3 5
样例输出
-
3 1
描述
小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一次最多能撕掉多少张海报,和他选择的海报是第几张贴出的。
题目链接:http://hihocoder.com/problemset/problem/1273
题目分析:枚举面与面之间的覆盖关系,用vector存,然后计算撕从开始到结束的每张海报一次能撕掉多少,这里要注意当前海报的四个角都被覆盖的情况,用状态压缩来记录即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int const MAX = 1e3 + 5;
int w, h, n;
int x1[MAX], y1[MAX], x2[MAX], y2[MAX];
int cnt[MAX];
vector<int> vt[MAX];
int Cal(int i, int j)
{
int res = 0;
if(x1[i] > x1[j] && x1[i] < x2[j] && y1[i] > y1[j] && y1[i] < y2[j])
res |= 1;
if(x1[i] > x1[j] && x1[i] < x2[j] && y2[i] > y1[j] && y2[i] < y2[j])
res |= 2;
if(x2[i] > x1[j] && x2[i] < x2[j] && y2[i] > y1[j] && y2[i] < y2[j])
res |= 4;
if(x2[i] > x1[j] && x2[i] < x2[j] && y1[i] > y1[j] && y1[i] < y2[j])
res |= 8;
return res;
}
void DFS(int st, int u, int &sta)
{
cnt[u] = 1;
int sz = vt[u].size();
for(int i = 0; i < sz; i++)
{
int v = vt[u][i];
if(!cnt[v])
{
sta |= Cal(st, v);
DFS(st, v, sta);
}
}
}
int main()
{
int min_x, max_x, min_y, max_y;
scanf("%d %d %d", &w, &h, &n);
for(int i = 1; i <= n; i++)
scanf("%d %d %d %d", &x1[i], &y1[i], &x2[i], &y2[i]);
for(int i = 1; i <= n; i++)
{
for(int j = i + 1; j <= n; j++)
{
min_x = max(x1[i], x1[j]);
max_x = min(x2[i], x2[j]);
min_y = max(y1[i], y1[j]);
max_y = min(y2[i], y2[j]);
if(min_x < max_x && min_y < max_y)
vt[i].push_back(j);
}
}
int ans = 0, id = 0;
for(int i = 1; i <= n; i++)
{
int sta = 0;
memset(cnt, 0, sizeof(cnt));
DFS(i, i, sta);
if(sta == 15)
continue;
int cur = 0;
for(int j = 1; j <= n; j++)
cur += cnt[j];
if(cur > ans)
{
ans = cur;
id = i;
}
}
printf("%d %d\n", ans, id);
}