链接:点击打开链接
题意:小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倾向于选择更早贴出的海报。
代码:
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int x1,y1,x2,y2;
}s[1005];
vector<int> G[1005];
int sum,use[1005],vis[1005];
void judge1(node a,node b){
if((a.x1>=b.x1&&a.x1<=b.x2)&&(a.y2>=b.y1&&a.y2<=b.y2))
sum|=(1<<0);
if((a.x2>=b.x1&&a.x2<=b.x2)&&(a.y2>=b.y1&&a.y2<=b.y2))
sum|=(1<<1);
if((a.x1>=b.x1&&a.x1<=b.x2)&&(a.y1>=b.y1&&a.y1<=b.y2))
sum|=(1<<2);
if((a.x2>=b.x1&&a.x2<=b.x2)&&(a.y1>=b.y1&&a.y1<=b.y2))
sum|=(1<<3);
}
int judge2(node a,node b){ //因为判断矩形相交情况较多,所以判断矩形不相交
if((b.x1>=a.x2)||(b.x2<=a.x1)||(b.y1>=a.y2)||(b.y2<=a.y1))
return 0;
return 1;
}
void dfs(int s){
int i,tmp;
vis[s]=1;
sum++;
for(i=0;i<G[s].size();i++){
tmp=G[s][i];
if(vis[tmp])
continue;
dfs(tmp);
}
}
int main(){ //处理出每个海报可以连带多少海报,直接建图dfs即可
int w,h,n,i,j,id,ans;
while(scanf("%d%d%d",&w,&h,&n)!=EOF){
for(i=1;i<=n;i++){
G[i].clear();
scanf("%d%d%d%d",&s[i].x1,&s[i].y1,&s[i].x2,&s[i].y2);
}
memset(use,0,sizeof(use));
for(i=n;i>=1;i--){
sum=0;
for(j=i+1;j<=n;j++){
judge1(s[i],s[j]);
if(sum==15) //如果四个角被压住则不能作为起点
use[i]=1;
if(judge2(s[i],s[j]))
G[i].push_back(j);
}
}
ans=1,id=n;
for(i=n-1;i>=1;i--){
sum=0;
if(use[i])
continue;
memset(vis,0,sizeof(vis));
dfs(i);
if(sum>=ans){
id=i;
ans=sum;
}
}
printf("%d %d\n",ans,id);
}
return 0;
}