POJ2836 Rectangular Covering(状压DP)

题目是平面上n个点,要用若干个矩形盖住它们,每个矩形上至少要包含2个点,问要用的矩形的面积和最少是多少。

容易反证得出每个矩形上四个角必定至少覆盖了两个点。然后就状压DP:

  • dp[S]表示覆盖的点集为S要用的最少矩形面积

转移我一开始是未覆盖的点和已覆盖的点构成一个矩形来转移,这是错的,因为这样子的结果是所有矩形都相连的最小面积和。

正确的是枚举还未被覆盖的矩形来转移。转移我用我为人人+队列。

有一点要注意的是,覆盖(0,0)和(0,2)两点要用的矩形是1*2,所以要特判一下两点斜率0或不存在时构成的矩形。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 #define INF (1<<29)
 7 
 8 bool isIn(int x1,int y1,int x2,int y2,int x,int y){
 9     if(x1>x2) swap(x1,x2);
10     if(y1>y2) swap(y1,y2);
11     return x1<=x && x<=x2 && y1<=y && y<=y2;
12 }
13 int area(int x1,int y1,int x2,int y2){
14     if(x1==x2) ++x2;
15     if(y1==y2) ++y2;
16     if(x1>x2) swap(x1,x2);
17     if(y1>y2) swap(y1,y2);
18     return (x2-x1)*(y2-y1);
19 }
20 int d[1<<15],sta[15][15];
21 bool inque[1<<15];
22 int main(){
23     int n,x[15],y[15];
24     while(~scanf("%d",&n) && n){
25         for(int i=0; i<n; ++i) scanf("%d%d",x+i,y+i);
26         for(int i=0; i<(1<<n); ++i) d[i]=INF;
27         queue<int> que;
28         memset(inque,0,sizeof(inque));
29         for(int i=0; i<n; ++i){
30             for(int j=i+1; j<n; ++j){
31                 int s=0;
32                 for(int k=0; k<n; ++k){
33                     if(isIn(x[i],y[i],x[j],y[j],x[k],y[k])) s|=(1<<k);
34                 }
35                 sta[i][j]=sta[j][i]=s;
36                 if(d[s]>area(x[i],y[i],x[j],y[j])){
37                     d[s]=area(x[i],y[i],x[j],y[j]);
38                     if(!inque[s|sta[i][j]]){
39                         inque[s]=1;
40                         que.push(s);
41                     }
42                 }
43             }
44         }
45         while(!que.empty()){
46             int s=que.front(); que.pop();
47             for(int i=0; i<n; ++i){
48                 for(int j=i+1; j<n; ++j){
49                     if(((s>>i)&1) && ((s>>j)&1)) continue;
50                     if(d[s|sta[i][j]]>d[s]+area(x[i],y[i],x[j],y[j])){
51                         d[s|sta[i][j]]=d[s]+area(x[i],y[i],x[j],y[j]);
52                         if(!inque[s|sta[i][j]]){
53                             inque[s|sta[i][j]]=1;
54                             que.push(s|sta[i][j]);
55                         }
56                     }
57                 }
58             }
59             inque[s]=0;
60         }
61         printf("%d\n",d[(1<<n)-1]);
62     }
63     return 0;
64 }

 

你可能感兴趣的:(POJ2836 Rectangular Covering(状压DP))