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