POJ2836--Rectangular Covering

题目大意:在一个平面里,有n个点,用若干矩形来覆盖所有点,每个矩形的所有边上都必须包含一共至少两个点,求最小总面积。

 

分析:状压DP。状态:dp[i]表示点集为i时的最小面积。

状态转移方程:dp[新点集] = min(dp[新点集] , dp[旧点集]+新矩形面积)


代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

struct Rect {
    int area;
    int pset;
}rect[300];

int dp[1<<16];
int x[20], y[20];
int n;

int main() {
    while(scanf("%d", &n) && n) {
        for(int i = 0; i < n; i++)
            scanf("%d%d", &x[i], &y[i]);
        int cnt = 0;
        for(int i = 0; i < n-1; i++) {
            for(int j = i+1; j < n; j++) {
                rect[cnt].area = max(1, abs(x[i]-x[j]))*max(1, abs(y[i]-y[j]));
                rect[cnt].pset = (1<<i) | (1<<j);
                for(int k = 0; k < n; k++) {
                    if((x[i]-x[k])*(x[j]-x[k]) <= 0 && (y[i]-y[k])*(y[j]-y[k]) <= 0)
                        rect[cnt].pset |= 1<<k;
                }
                cnt++;
            }
        }
        fill(dp, dp+(1<<16), 1<<30);
        dp[0] = 0;
        for(int i = 0; i < cnt; i++) {
            for(int j = 0; j < 1<<n; j++) {
                int p = j|rect[i].pset;
                if(dp[j] != 1<<30 && p != j) {
                    dp[p] = min(dp[p], dp[j]+rect[i].area);

                }
            }
        }
        printf("%d\n", dp[(1<<n)-1]);
    }
    return 0;
}


你可能感兴趣的:(POJ2836--Rectangular Covering)