Rectangular Covering [POJ2836] [状压DP]

时间:2021-07-12 10:28:40

题意

平面上有 n (2 ≤ n ≤ 15) 个点,现用平行于坐标轴的矩形去覆盖所有点,每个矩形至少盖两个点,矩形面积不可为0,求这些矩形的最小面积。

Input

The input consists of several test cases. Each test cases begins with a line containing a single integer n (2 ≤ n ≤ 15). Each of the next n lines contains two integers xy (−1,000 ≤ xy ≤ 1,000) giving the coordinates of a point. It is assumed that no two points are the same as each other. A single zero follows the last test case.

Output

Output the minimum total area of rectangles on a separate line for each test case.

Sample Input

2
0 1
1 0
0

Sample Output

1

Analysis

枚举两个个点,再算包含在这两个点的点,算进一个矩形

然后在枚举矩形,进行状压DP

Code

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector> using std::vector;
using std::min;
using std::max; const int MAXN = ;
const int INF = 0x3f3f3f3f; struct POINT
{
int x;
int y;
} p[MAXN + ]; struct RECTANGLE
{
int area;
int cover;
} r[MAXN * MAXN]; int n;
int dp[ << MAXN];
int area[MAXN + ][MAXN + ];
int cnt; int abs(int x)
{
return x > ? x : -x;
} void Read()
{
for (int i = ; i < n; ++i)
{
scanf("%d%d", &p[i].x, &p[i].y);
}
} void Init()
{
cnt = ;
for (int i = ; i < n; ++i)
{
for (int j = ; j < i; ++j)
{
if (j != i)
{
int width = abs(p[i].x - p[j].x) == ? : abs(p[i].x - p[j].x);
int height = abs(p[i].y - p[j].y) == ? : abs(p[i].y - p[j].y);
r[cnt].area = width * height;
r[cnt].cover = ;
for (int k = ; k < n; ++k)
{
if (p[k].x >= min(p[i].x, p[j].x) && p[k].x <= max(p[i].x, p[j].x) &&
p[k].y >= min(p[i].y, p[j].y) && p[k].y <= max(p[i].y, p[j].y))
{
r[cnt].cover |= ( << k);
}
}
++cnt;
}
}
}
} void Dp()
{
memset(dp, 0x3f, sizeof(dp));
dp[] = ;
for (int S = ; S < ( << n); ++S)
{
if (dp[S] != INF)
{
for (int i = ; i < cnt; ++i)
{
int news = S | r[i].cover;
if (news != S)
{
dp[news] = min(dp[news], dp[S] + r[i].area);
}
}
}
}
printf("%d\n", dp[( << n) - ]);
} int main()
{
while (scanf("%d", &n) == && n)
{
Read();
Init();
Dp();
} return ;
}