zoukankan      html  css  js  c++  java
  • 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
    ",d[(1<<n)-1]);
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    Visual Studio 2008 可扩展性开发(一):VS概览
    CButtonST使用技巧: CButtonST简介
    Doxygen + Graphviz + Htmlhelp, 成为文档好手
    Django的多数据库处理(垂直分库和水平分库)
    赫曼米勒中国| 设计,让世界更美好。
    maccman/juggernaut
    aptget y install buildessential
    QT分析之WebKit(三)
    Django的多数据库支持,太酷了~
    我们的征途是星辰大海#
  • 原文地址:https://www.cnblogs.com/WABoss/p/5192326.html
Copyright © 2011-2022 走看看