您的位置:首页 > 其它

hiho1273 几何操作+dfs

2016-03-14 14:25 302 查看
学习大牛写的

题目:


描述

小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一次最多能撕掉多少张海报,和他选择的海报是第几张贴出的。

思路:

1、首先需要有一个函数判断两张海报是否覆盖,a的左下在b的右上的上面显然不重叠(非严格大于),四个角四种对应关系是不覆盖的,其他都是覆盖的,将覆盖的海报建边,为搜索打基础。

2、需要判断当前海报是否四个角被覆盖,因为n是1000,所以暴力也不会超时。依次判断当前海报的四个角和后面的海报的覆盖关系。这个判断就简单了,看点是否在面内,不能再线上,必须在面内。若四个角都被覆盖显然不行,用数组res标记

3、dfs搜索,维护最大值

ps:最烦几何了,各种麻烦。不过思路清晰严谨一点这道题不难。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 1005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 100000000
int w , h , n;
int vis[maxn];
bool res[maxn];
vector<int>G[maxn];

struct node
{
int x1 , x2 ;
int y1 , y2;
}a[maxn];

bool judge(int d , int u) //判断u是否覆盖d
{
if(a[d].x1 >= a[u].x2) return 0;
else if(a[u].x1 >= a[d].x2 ) return 0;
else if(a[d].y1 >= a[u].y2 ) return 0;
else if(a[u].y1 >= a[d].y2 ) return 0;
else return 1;
}

bool judge2(int root , int x , int y) //判断某个点是否被覆盖
{
if(x > a[root].x1 && x < a[root].x2 && y > a[root].y1 && y < a[root].y2) return true;
return false;
}

int dfs(int root)
{
if(vis[root]) return 0;
vis[root] = 1;
int num = 1;
for(int i = 0 ; i < G[root].size() ; i ++)
{
num += dfs(G[root][i]);
}
return num;
}

int main()
{
while(scanf("%d %d %d" , &w , &h , &n) != EOF)
{
for(int i = 0 ; i < n ; i ++)
{
scanf("%d %d %d %d" , &a[i].x1 , &a[i].y1 , &a[i].x2 , &a[i].y2);
G[i].clear();
res[i] = true;
}
for(int i = 0 ; i < n ; i ++)
{
int flag = 0;
for(int j = i + 1 ; j < n ; j ++)
{
if(judge(i , j)) G[i].push_back(j);
if( judge2(j , a[i].x1 , a[i].y1) ) flag |= 1;
if( judge2(j , a[i].x2 , a[i].y2) ) flag |= 2;
if( judge2(j , a[i].x2 , a[i].y1) ) flag |= 4;
if( judge2(j , a[i].x1 , a[i].y2) ) flag |= 8;
}
if(flag == 15) res[i] = 0;   //判断四个角是否被全覆盖
}
int ans = 0, pos = 0;
for(int i = 0 ; i < n ; i ++)
{
if(res[i])
{
mem(vis , 0);
int tmp = dfs(i);
if(tmp > ans)
{
ans = tmp;pos = i+1;
}
if(ans >= n - i - 1) break;
}
}
printf("%d %d\n" , ans , pos);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: