练搜索的好题。
按一般思路来说,应该是按每一个矩形搜索,分别判断它会覆盖哪些点。当所有矩形都用完,并且覆盖了所有的点时,再判断矩形之间有没有遮挡,此时就得出了一个可能的解。但这样包含了大量的无效情况,因为在大多数情况下矩形用完时不能覆盖所有的点,因此大大浪费了时间。 用这种方法会 TLE 。
所以要换一个思路,想要去掉这些无效的情况,我们就需要按点进行搜索。对于某一个点,我们枚举它会被放到哪个矩形里,这样每次搜索到树根时矩形一定包含了所有的点,之后只需要判断矩形有没有互相遮挡就好了。
#include <stdio.h>
#include <iostream>
using namespace std;
#define MAXN 505
#define INF 0x3f3f3f3f
int n, k, ans = INF;
struct node
{
int x, y;
}point[MAXN];
struct Node
{
int X1 = 0, X2 = INF;
int Y1 = 0, Y2 = INF;
int cnt = 0;
int calculate_area()
{
if (!cnt) return 0;
return (X1 - X2) * (Y1 - Y2);
}
void push(node a)
{
X1 = max(X1, a.x);
X2 = min(X2, a.x);
Y1 = max(Y1, a.y);
Y2 = min(Y2, a.y);
cnt = 1;
}
bool inrec(Node a)
{
return (a.X1>=X1 && a.X2<=X1 && a.Y1>=Y1 && a.Y2<=Y1) ||
(a.X1>=X2 && a.X2<=X2 && a.Y1>=Y1 && a.Y2<=Y1) ||
(a.X1>=X1 && a.X2<=X1 && a.Y1>=Y2 && a.Y2<=Y2) ||
(a.X1>=X2 && a.X2<=X2 && a.Y1>=Y2 && a.Y2<=Y2);
}
}rectangle[5];
bool check()
{
for (int i=1;i<=k;i++)
{
for (int j=i+1;j<=k;j++)
{
if (rectangle[i].inrec(rectangle[j])) return 0;
}
}
return 1;
}
void dfs(int num, int area)
{
if (ans <= area) return;
if (num > n)
{
if (check())
ans = area;
return;
}
for (int i=1;i<=k;i++)
{
Node temp = rectangle[i];
rectangle[i].push(point[num]);
dfs(num + 1, area - temp.calculate_area() + rectangle[i].calculate_area());
rectangle[i] = temp;
}
}
int main(void)
{
cin >> n >> k;
for (int i=1;i<=n;i++)
{
cin >> point[i].x >> point[i].y;
}
dfs(1, 0);
cout << ans;
return 0;
}