文章標題 POJ : Rectangular Covering(狀壓DP)

Rectangular Covering

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 x, y (−1,000 ≤ x, y ≤ 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.

題意:在二維平面上有n個點,然後要我們選取與座標軸平行的矩形將這n個點覆蓋,每個矩形至少要覆蓋上兩個點,然後要我們求出覆蓋所有的點所需要的矩形的面積和最小是多少。
分析:由於點的數目只有15,所以可以用狀態壓縮,並且先預處理出任意兩點所形成的矩形,記錄這兩個點所形成的矩形的面積和所覆蓋的點對應的狀態,然後對於當前的這個矩形 所對應的面積爲area,所對應的狀態爲s,則dp[i|s]=min(dp[i|s],dp[i]+area).
代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
typedef long long ll;

const int mod=1e9+7;
const int maxn=20;

int n;
struct node {
    int x,y;
}p[maxn];
int s[maxn*maxn];
int area[maxn*maxn];
int dp[1<<15];

int main()
{
    while (scanf ("%d",&n)&&n){
        for (int i=0;i<n;i++){
            scanf ("%d%d",&p[i].x,&p[i].y);
        }
        for (int i=0;i<(1<<n);i++)dp[i]=1e9;
        int cnt=0;
        for (int i=0;i<n;i++){
            for (int j=i+1;j<n;j++){
                s[cnt]=(1<<i)|(1<<j);//對應的狀態,area表示對應的面積 
                for (int k=0;k<n;k++){//枚舉點看有哪些點在矩形上 
                    if ((p[k].x-p[i].x)*(p[k].x-p[j].x)<=0&&(p[k].y-p[i].y)*(p[k].y-p[j].y)<=0)
                        s[cnt]=s[cnt]|(1<<k);//更新狀態 
                }
                if (p[i].x==p[j].x)area[cnt]=fabs(p[i].y-p[j].y);//兩個點平行y軸 
                else if (p[i].y==p[j].y)area[cnt]=fabs(p[i].x-p[j].x);//平行x軸 
                else area[cnt]=(fabs(p[i].x-p[j].x))*(fabs(p[i].y-p[j].y));
                cnt++;
            }
        }
        dp[0]=0;
        for (int i=0;i<(1<<n);i++){
            for (int j=0;j<cnt;j++){
                dp[i|(s[j])]=min(dp[i|s[j]],dp[i]+area[j]);
            }
        }
        printf ("%d\n",dp[(1<<n)-1]);
    }
    return 0;
}
發佈了191 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章