题目大意
在平面上有 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。各个矩形必须完全分开(边线与顶点也都不能重合)。
输入描述 Input Description
n k
xl y1
x2 y2
… …
xn yn (0<=xi,yi<=500)输出描述 Output Description
一个整数,即满足条件的最小的矩形面积之和。
样例输入 Sample Input
4 2
1 1
2 2
3 6
0 7样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
k<4
(官方是k<=4,但是标程解法在k=4时是有反例的。官方的数据也没有出现k=4的情况)
分析
这个其实暴搜就可以了。
按照每个点,搜覆盖它的矩形。
这里比较有趣的一点是,我原以为把点先排序后再搜,这样会快一些。
但是并不,甚至还TLE了!可能是因为不排序时,点比较分散,dfs的时候能很快找到不符合条件的情况。
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 60, K = 10, inf = 1<<30;
struct NODE { //这里储存矩形。 lx和ly是矩形左下角的坐标,rx和ry是右上角的
int lx, ly, rx, ry;
}s[K];
struct Point {
int x, y;
}e[N];
int n, k, ans = inf;
bool cmp(Point a, Point b) {
if(a.x == b.x) return a.y < b.y;
return a.x > b.x;
}
int getS() { //矩形面积
int S = 0;
for(int i = 1; i <= k; i++) {
S += (s[i].rx - s[i].lx) * (s[i].ry - s[i].ly);
}
return S;
}
bool judge(NODE a, NODE b) { //判断两个矩形是否合法
if(a.lx == inf || a.ly == inf || a.rx == -inf || a.ry == -inf)
return 1;
if(b.lx == inf || b.ly == inf || b.rx == -inf || b.ry == -inf)
return 1;
if(a.lx > b.rx || a.ly > b.ry)
return 1;
if(b.lx > a.rx || b.ly > a.ry)
return 1;
return 0;
}
bool check() {
int flag = 1;
for(int i = 1; i <= k; i++) {
for(int j = i+1; j <= k; j++) {
flag = judge(s[i], s[j]);
}
}
return flag;
}
void dfs(int v) {
if(v == n+1) {
ans = min(ans, getS());
return ;
}
for(int i = 1; i <= k; i++) {
NODE tmp = s[i];
s[i].lx = min(s[i].lx, e[v].x);
s[i].ly = min(s[i].ly, e[v].y);
s[i].rx = max(s[i].rx, e[v].x);
s[i].ry = max(s[i].ry, e[v].y);
if(check() && getS() < ans)
dfs(v+1);
s[i] = tmp;
}
}
int main() {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++)
scanf("%d%d", &e[i].x, &e[i].y);
// sort(e+1, e+1+n, cmp);
for(int i = 1; i <= k; i++) {
s[i].lx = s[i].ly = inf;
s[i].rx = s[i].ry = -inf;
}
dfs(1);
printf("%d\n", ans);
return 0;
}