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 }
  • 相关阅读:
    201521123093 java 第二周学习总结
    201521123093 java 第一周总结
    Word 2010怎么自动添加文献引用
    动态链接库(dll)文件的动态调用(使用动态链接库,解析Wis文件--测井数据文件的一种)
    open inventor 学习笔记
    井眼轨迹的三次样条插值 (vs + QT + coin3d)
    VS2010 + QT 5 +open inventor 环境配置
    我的第一个项目(人力资源管理之报表管理)
    B-tree 和 B+tree
    mysql count(*)与count(1)的区别
  • 原文地址:https://www.cnblogs.com/WABoss/p/5192326.html
Copyright © 2011-2022 走看看