hiho一下 第140周-清理海报(DAG+dfs)

记录一个菜逼的成长。。

题目链接

官方题解
题解里面貌似有错
hiho一下 第140周
这里应该还有条3->4的边

有人会问为什么会有2->4这条边,从图上看2的四个点都被覆盖了。
这就是建图时要注意的地方了,建图时我们只要根据两个矩形是否相交建图就可以了,不必去管矩形的四个点是否被覆盖。
因为虽然2的四个点都被覆盖,但是2是作为1和4之间的关联的。撕1时,会先撕去2,然后再撕去4.所以这里要有条2->4的边。这样在搜索时就不会漏了。

然后枚举第一次要撕去的海报,这里判断一下矩形的四个点是否被覆盖。
只要有一个点未被覆盖就可以直接去搜索了。

PS:这里我用y1数组不知道为什么会CE..说定义重了。然而程序里只定义了一次。。

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define cl(a,b) memset(a,b,sizeof(a))
const int maxn = 1000 + 10;
int x1[maxn],y11[maxn],x2[maxn],y2[maxn];
int f[maxn][4],vis[maxn];
vector<int>g[maxn];
int w,h,n;
bool overlap(int i, int j)
{
    return !(x1[i] >= x2[j] || x1[j] >= x2[i] || y11[i] >= y2[j] || y11[j] >= y2[i]);
}
bool check(int i,int x,int y)
{
    return x >= x1[i] && x <= x2[i] && y >= y11[i] && y <= y2[i];
}
int dfs(int x)
{
    int ans = 0;
    for( int i = 0; i < g[x].size(); i++ ){
        if(!vis[g[x][i]]){
            vis[g[x][i]] = 1;
            ans += dfs(g[x][i]);
        }
    }
    return ans + 1;
}
int main()
{
    while(~scanf("%d%d%d",&w,&h,&n)){
        for( int i = 1; i <= n; i++ ){
            scanf("%d%d%d%d",&x1[i],&y11[i],&x2[i],&y2[i]);
        }
        for( int i = 1; i <= n; i++ ){
            for( int j = i+1; j <= n; j++ ){
                if(check(j,x1[i],y11[i]))f[i][0] = 1;
                if(check(j,x1[i],y2[i]))f[i][1] = 1;
                if(check(j,x2[i],y2[i]))f[i][2] = 1;
                if(check(j,x2[i],y11[i]))f[i][3] = 1;
            }
        }
        for( int i = 1; i <= n; i++ ){
            for( int j = 1; j < i; j++ ){
                if(overlap(i,j))g[j].pb(i);
            }
        }
        int  mx = -1;
        int id;
        for( int i = 1; i <= n; i++ ){
            if(f[i][0] && f[i][1] && f[i][2] && f[i][3])continue;
            cl(vis,0);
            int ret = dfs(i);
            if(ret > mx){
                mx = ret;
                id = i;
            }
        }
        printf("%d %d\n",mx,id);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值