NOIP 2002 矩形覆盖

当年的一道D2T1,一眼看上去很简单的样子,但是实际做起来没那么容易。

看一眼数据范围,很好可以考虑搜索,首先想到的是搜什么。

如果从矩形开始搜,虽然至多只有4个矩形,但是可以有很多很多很多种的组合。因为一个矩形要么由对角线上顶点确定,要么由一个顶点与不包含该顶点的两边上的各一点确定,这样搜索会有2500^4种情况显然会炸。

那么考虑从点开始搜,点能怎么搜呢?依次考虑能把它放到哪个矩形中即可。实现时用一个结构体存储矩形(最多就四个),每个点依次放入不同矩形,同时维护放入矩形的边界然后搜下一个点,如果搜到一个矩形发现它还没有被使用,就把它的边界全部设为点的坐标来构建一个新矩形。加上一个剪枝快到飞起。

呆马:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,ans=0x7f7f7f7f;
struct node
{
    int x,y;
}dot[60];
struct martix
{
    int l,r,f,t;
    bool flag;
}jz[5];
bool in(martix k,int x,int y)
{
    if(x<=k.r&&x>=k.l&&y<=k.f&&y>=k.t) return 1;
    return 0;
}
bool judge(martix k,martix m)
{
    if(in(k,m.l,m.f)) return 0;
    if(in(k,m.r,m.f)) return 0;
    if(in(k,m.l,m.t)) return 0;
    if(in(k,m.r,m.t)) return 0;
    return 1;
}
void dfs(int sum)
{
    int val=0;
    for(int i=1;i<=m;i++)
    {
        if(jz[i].flag)
        {
            for(int j=i+1;j<=m;j++) 
                if(!judge(jz[i],jz[j])) return;
        }
        val+=(jz[i].r-jz[i].l)*(jz[i].f-jz[i].t);
    }
    if(val>=ans) return;
    if(sum>n)
    {
        ans=val;
        return;
    }
    for(int i=1;i<=m;i++)
    {
        martix tmp=jz[i];
        if(!jz[i].flag)
        {
            jz[i].flag=1;
            jz[i].l=jz[i].r=dot[sum].x;
            jz[i].f=jz[i].t=dot[sum].y;
            dfs(sum+1);
            jz[i]=tmp;
            break;
        }
        else
        {
            jz[i].l=min(jz[i].l,dot[sum].x);
            jz[i].r=max(jz[i].r,dot[sum].x);
            jz[i].f=max(jz[i].f,dot[sum].y);
            jz[i].t=min(jz[i].t,dot[sum].y);
            dfs(sum+1);
            jz[i]=tmp;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&dot[i].x,&dot[i].y);
    dfs(1);
    printf("%d",ans);
    return 0;
}
        

 

posted @ 2019-04-19 22:09  .Terena  阅读(159)  评论(0编辑  收藏  举报