NOIP 2002 矩形覆盖

题目描述
在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示。例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一。
这里写图片描述
这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢。约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。


【题目分析】
暴搜。


【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n,k,ans=inf;
struct ma{int x1,y1,x2,y2;}b[5];
struct node{int x,y;}a[51];
bool judgein()
{
    for (int i=1;i<=k;++i)
        if (b[i].x1!=inf) for (int j=1;j<=k;++j)
            if (b[j].x1!=inf)
            {
                if (i!=j&&b[i].x2>=b[j].x1&&b[i].x1<=b[j].x1&&b[i].y1>=b[j].y1&&b[i].y1<=b[j].y2) return true;
                else if (i!=j&&b[i].x2>=b[j].x1&&b[i].x1<=b[j].x1&&b[i].y2>=b[j].y1&&b[i].y2<=b[j].y2) return true;
            }
    return false;
}
int cal()
{
    int ret=0;
    for (int i=1;i<=k;++i)
    {
        if (b[i].x1==inf) continue;
        ret+=(b[i].x2-b[i].x1)*(b[i].y2-b[i].y1);
    }
    return ret;
}
void dfs(int now)
{
    if (judgein()) return; 
    if (now>n)
    {
        ans=min(ans,cal());
        return ;
    }
    if (cal()>=ans) return ;
    for (int i=1;i<=k;++i)
    {
        int flag=1;
        for (int j=1;j<=k;++j)
            if (i!=j&&a[now].x>=b[j].x1&&a[now].x<=b[j].x2&&a[now].y>=b[j].y1&&a[now].y<=b[j].y2) flag=0;
        if (!flag) continue;
        ma back=b[i]; 
        b[i].x1=min(b[i].x1,a[now].x);
        b[i].y1=min(b[i].y1,a[now].y);
        b[i].x2=max(b[i].x2,a[now].x);
        b[i].y2=max(b[i].y2,a[now].y);
        dfs(now+1);
        b[i]=back;
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y);
    for (int i=1;i<=k;++i)
    {
        b[i].x1=inf; b[i].x2=-inf;
        b[i].y1=inf; b[i].y2=-inf;
    }
    dfs(1);
    printf("%d\n",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值