题意:
坐标平面上有n各点,用任意大小(非零)的矩形覆盖它们,求最省的矩形的总面积。
解析:
预处理,将n个点两个两个组合构成多个矩形,然后将在矩形内部的点更新进矩形中。
然后就是dp的过程了:
dp[0] = 0。初始时集合中没有点,并且面积为0。
dp[nowS] = min ( dp[nowS], dp[s] + area)。
当前的点集的矩阵取,还是不取。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 16;
int x[maxn], y[maxn];
int dp[1 << maxn];
struct Rectangle
{
int cover; //点集
int area; //面积
Rectangle(){}
Rectangle(int _cover, int _area)
{
cover = _cover;
area = _area;
}
void addPoint(int x)
{
cover |= (1 << x);
}
};
int area(int i, int j)
{
return max(1, abs(x[i] - x[j])) * max(1, abs(y[i] - y[j]));
}
bool in(int i, int j, int k)
{
return ((x[i] - x[k]) * (x[j] - x[k]) <= 0) && ((y[i] - y[k]) * (y[j] - y[k]) <= 0);
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int n;
while (scanf("%d", &n) && n)
{
for (int i = 0; i < n; i++)
{
scanf("%d%d", &x[i], &y[i]);
}
vector<Rectangle> vec;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
Rectangle tmp((1 << i) | (1 << j), area(i, j));
for (int k = 0; k < n; k++)
{
if (in(i, j, k))
{
tmp.addPoint(k);
}
}
vec.push_back(tmp);
}
}
memset(dp, inf, sizeof(dp));
dp[0] = 0;
int sz = vec.size();
for (int i = 0; i < sz; i++)
{
for (int state = 0; state < (1 << n); state++)
{
int nowS = state | vec[i].cover;
if (dp[state] != inf)
{
dp[nowS] = min(dp[nowS], dp[state] + vec[i].area);
}
}
}
printf("%d\n", dp[(1 << n) - 1]);
}
return 0;
}