题目描述
在平面上有 个点( ),每个点用一对整数坐标表示。例如:当 时, 个点的坐标分另为: ( ), ( ), ( ), ( ),见图一。
这些点可以用
个矩形(
)全部覆盖,矩形的边平行于坐标轴。当
时,可用如图二的两个矩形
覆盖,
面积和为
。问题是当
个点坐标和
给出后,怎样才能使得覆盖所有点的
个矩形的面积之和为最小呢?
约定:覆盖一个点的矩形面积为
;覆盖平行于坐标轴直线上点的矩形面积也为
。各个矩形必须完全分开(边线与顶点也都不能重合)。
输入格式
(
)
输出格式
输出至屏幕。格式为:
个整数,即满足条件的最小的矩形面积之和。
输入输出样例
输入 #1 复制
4 2
1 1
2 2
3 6
0 7
输出 #1 复制
4
思路
这么一道数据小的题目如果不用搜索真是对不起这数据
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0x3fffffff,t;
struct zj1{
int x,y;
};
zj1 f[51];
struct zj2{
int a,b,c,d;
};
zj2 k[5];
bool check(int x){
for(int i=1;i<=t;i++){
if(i==x)continue;
if(k[i].a<=k[x].a&&k[i].a>=k[x].b&&k[i].c>=k[x].c&&k[i].c<=k[x].d)return 0;
if(k[i].a<=k[x].a&&k[i].a>=k[x].b&&k[i].d>=k[x].c&&k[i].d<=k[x].d)return 0;
if(k[i].b<=k[x].a&&k[i].b>=k[x].b&&k[i].c>=k[x].c&&k[i].c<=k[x].d)return 0;
if(k[i].b<=k[x].a&&k[i].b>=k[x].b&&k[i].d>=k[x].c&&k[i].d<=k[x].d)return 0;
}
return 1;
}
void dfs(int x){
int sum=0;
for(int i=1;i<=t;i++)
sum+=(k[i].a-k[i].b)*(k[i].d-k[i].c);
if(x>n){
ans=min(ans,sum);
return;
}
if(sum>=ans)
return;
for(int j=1;j<=t;j++){
int a=k[j].a,b=k[j].b,c=k[j].c,d=k[j].d;
k[j].a=max(f[x].x,k[j].a);
k[j].b=min(f[x].x,k[j].b);
k[j].c=min(f[x].y,k[j].c);
k[j].d=max(f[x].y,k[j].d);
if(check(j))
dfs(x+1);
k[j].a=a;
k[j].b=b;
k[j].c=c;
k[j].d=d;
}
if(t<m){
t++;
k[t].b=f[x].x;
k[t].a=f[x].x;
k[t].c=f[x].y;
k[t].d=f[x].y;
dfs(x+1);
t--;
}
return;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&f[i].x,&f[i].y);
dfs(1);
cout<<ans;
return 0;
}