Hihocoder hiho一下 第140周 清理海报

题目1 : 清理海报

时间限制: 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

先根据判断两个海报是否相交和四角的覆盖---得到最后那些可以当做撕海报的源点---和海报之间的联通性---

然后从每个海报源点开始dfs-.-  最后统计最大值


代码:

#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int x1,x2,y1,y2;
    bool jiao[4];
}book[1010];
bool pan(int i,int j)
{
    if (book[i].x1>=book[j].x2||book[i].x2<=book[j].x1||book[i].y1>=book[j].y2||book[i].y2<=book[j].y1)
        return false;
    if (book[i].y1<book[j].y2&&book[i].y1>book[j].y1)
    {
        if (book[i].x1>book[j].x1&&book[i].x1<book[j].x2)
            book[i].jiao[0]=true;
        if (book[i].x2>book[j].x1&&book[i].x2<book[j].x2)
            book[i].jiao[1]=true;
    }
    if (book[i].y2<book[j].y2&&book[i].y2>book[j].y1)
    {
        if (book[i].x1>book[j].x1&&book[i].x1<book[j].x2)
            book[i].jiao[2]=true;
        if (book[i].x2>book[j].x1&&book[i].x2<book[j].x2)
            book[i].jiao[3]=true;
    }
    return true;
}
bool fa[1010];
int ans1,ans2,wx;
vector<int > V[1010];
void dfs(int x)
{
    fa[x]=true;
    ans2++;
    for (int i=0;i<V[x].size();i++)
    {
        int v=V[x][i];
        if (fa[v]) continue;
        dfs(v);
    }
}
int main()
{
    int w,h,n;
    cin>>w>>h>>n;
    for (int i=1;i<=n;i++)
        cin>>book[i].x1>>book[i].y1>>book[i].x2>>book[i].y2;
    for (int i=1;i<n;i++)
    {
        for (int j=i+1;j<=n;j++)
        {
            if (pan(i,j))
            {
                V[i].push_back(j);
            }
        }
    }
    bool fafe;
    ans1=0;
    for (int i=1;i<=n;i++)
    {
        fafe=false;
        for (int j=0;j<4;j++)
            if (!book[i].jiao[j])
            {
                fafe=true;
                break;
            }
        if (fafe)
        {
            fill(fa,fa+n+1,false);
            ans2=0;dfs(i);
            if (ans2>ans1)
            {
                ans1=ans2;
                wx=i;
            }
        }
    }
    cout<<ans1<<' '<<wx<<endl;
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值