Rectangular Covering [POJ2836] [状压DP]

题意

平面上有 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

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <vector>
  5  
  6 using std::vector;
  7 using std::min;
  8 using std::max;
  9  
 10 const int MAXN = 15;
 11 const int INF = 0x3f3f3f3f;
 12  
 13 struct POINT
 14 {
 15     int x;
 16     int y;
 17 } p[MAXN + 1];
 18  
 19 struct RECTANGLE
 20 {
 21     int area;
 22     int cover;
 23 } r[MAXN * MAXN];
 24  
 25 int n;
 26 int dp[1 << MAXN];
 27 int area[MAXN + 1][MAXN + 1];
 28 int cnt;
 29  
 30 int abs(int x)
 31 {
 32     return x > 0 ? x : -x;
 33 }
 34  
 35 void Read()
 36 {
 37     for (int i = 0; i < n; ++i)
 38     {
 39         scanf("%d%d", &p[i].x, &p[i].y);
 40     }
 41 }
 42  
 43 void Init()
 44 {
 45     cnt = 0;
 46     for (int i = 0; i < n; ++i)
 47     {
 48         for (int j = 0; j < i; ++j)
 49         {
 50             if (j != i)
 51             {
 52                 int width = abs(p[i].x - p[j].x) == 0 ? 1 : abs(p[i].x - p[j].x);
 53                 int height = abs(p[i].y - p[j].y) == 0 ? 1 : abs(p[i].y - p[j].y);
 54                 r[cnt].area = width * height;
 55                 r[cnt].cover = 0;
 56                 for (int k = 0; k < n; ++k)
 57                 {
 58                     if (p[k].x >= min(p[i].x, p[j].x) && p[k].x <= max(p[i].x, p[j].x) &&
 59                             p[k].y >= min(p[i].y, p[j].y) && p[k].y <= max(p[i].y, p[j].y))
 60                     {
 61                         r[cnt].cover |= (1 << k);
 62                     }
 63                 }
 64                 ++cnt;
 65             }
 66         }
 67     }
 68 }
 69  
 70 void Dp()
 71 {
 72     memset(dp, 0x3f, sizeof(dp));
 73     dp[0] = 0;
 74     for (int S = 0; S < (1 << n); ++S)
 75     {
 76         if (dp[S] != INF)
 77         {
 78             for (int i = 0; i < cnt; ++i)
 79             {
 80                 int news = S | r[i].cover;
 81                 if (news != S)
 82                 {
 83                     dp[news] = min(dp[news], dp[S] + r[i].area);
 84                 }
 85             }
 86         }
 87     }
 88     printf("%d\n", dp[(1 << n) - 1]);
 89 }
 90  
 91 int main()
 92 {
 93     while (scanf("%d", &n) == 1 && n)
 94     {
 95         Read();
 96         Init();
 97         Dp();
 98     }
 99  
100     return 0;
101 }
View Code
posted @ 2018-07-15 17:38  iBilllee  阅读(118)  评论(0编辑  收藏  举报