洛谷P1034矩形覆盖题解--zhengjun
题目描述
在平面上有 \(n\) 个点(\(n \le 50\)),每个点用一对整数坐标表示。例如:当 \(n=4\) 时,\(4\) 个点的坐标分另为:\(p_1\)(\(1,1\)),\(p_2\)(\(2,2\)),\(p_3\)(\(3,6\)),\(p_4\)(\(0,7\)),见图一。
这些点可以用 \(k\) 个矩形(\(1 \le k \le 4\))全部覆盖,矩形的边平行于坐标轴。当 \(k=2\) 时,可用如图二的两个矩形 \(s_1,s_2\) 覆盖,\(s_1,s_2\) 面积和为 \(4\)。问题是当 \(n\) 个点坐标和 \(k\) 给出后,怎样才能使得覆盖所有点的 \(k\) 个矩形的面积之和为最小呢?
约定:覆盖一个点的矩形面积为 \(0\);覆盖平行于坐标轴直线上点的矩形面积也为 \(0\)。各个矩形必须完全分开(边线与顶点也都不能重合)。
输入格式
\(n k\)
\(x_1 y_1\)
\(x_2 y_2\)
\(... ...\)
\(x_n y_n\)
(\(0 \le x_i,y_i \le 500\))
输出格式
输出至屏幕。格式为:
\(1\) 个整数,即满足条件的最小的矩形面积之和。
输入输出样例
输入 #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;
}