1. 程式人生 > >POJ 2836 Rectangular Covering(狀壓DP->覆蓋所有點的最小矩形面積和)

POJ 2836 Rectangular Covering(狀壓DP->覆蓋所有點的最小矩形面積和)


Rectangular Covering Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit  Status

Description

n points are given on the Cartesian plane. Now you have to use some rectangles whose sides are parallel to the axes to cover them. Every point must be covered. And a point can be covered by several rectangles. Each rectangle should cover at least two points including those that fall on its border. Rectangles should have integral dimensions. Degenerate cases (rectangles with zero area) are not allowed. How will you choose the rectangles so as to minimize the total area of them?

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

Hint

The total area is calculated by adding up the areas of rectangles used.


因為要面積最小,一定是以每次覆蓋兩個點為主,並讓這兩個點在矩形的對角。
此題不可以出現面積為0的矩形,所以當出現x[i]==x[j]或者y[i]==y[j]時,讓它為0的這邊的邊長變成1。

這題將兩個點之間的面積可以覆蓋的最多點數作為一個狀態封裝起來,,,一個很重要的思維點;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 16;
int dp[1<<N], x[N], y[N], cover[N][N], area[N][N];


int main()
{
    int n;
    while(scanf("%d", &n),n)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d %d", &x[i], &y[i]);
        }
        memset(cover,0,sizeof(cover));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                int a1=max(x[i],x[j]), a2=min(x[i],x[j]);
                int b1=max(y[i],y[j]), b2=min(y[i],y[j]);
                for(int k=0;k<n;k++)
                {
                    if(x[k]>=a2&&x[k]<=a1&&y[k]>=b2&&y[k]<=b1)
                    {
                        cover[i][j]|=(1<<k);
                        cover[j][i]=cover[i][j];
                    }
                }
                a1=a1-a2?a1-a2:1, b1=b1-b2?b1-b2:1;
                area[i][j]=area[j][i]=a1*b1;
            }
        }
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        for(int i=0;i<(1<<n);i++)
        {
            if(dp[i]==-1)
                continue;
            for(int j=0;j<n;j++)
            {
                for(int k=0;k<n;k++)
                {
                    int state=i|(cover[j][k]);
                    if(dp[state]==-1||dp[state]>dp[i]+area[j][k])
                        dp[state]=dp[i]+area[j][k];
                }
            }
        }
        printf("%d\n",dp[(1<<n)-1]);
    }
    return 0;
}