NOIP 2002 矩形覆盖

来源:互联网 发布:手机漏洞检测软件 编辑:程序博客网 时间:2024/06/07 22:20

题目描述
在平面上有 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);}
0 0