zoukankan      html  css  js  c++  java
  • BZOJ1052 [HAOI2007]覆盖问题

    1052: [HAOI2007]覆盖问题

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2401  Solved: 1101
    [Submit][Status][Discuss]

    Description

      某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄
    膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建
    立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行与坐标轴,一个点如果在
    正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。

    Input

      第一行有一个正整数N,表示有多少棵树。接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证
    不会有2个树的坐标相同。

    Output

      一行,输出最小的L值。

    Sample Input

    4
    0 1
    0 -1
    1 0
    -1 0

    Sample Output

    1

    HINT

    100%的数据,N<=20000

     很容易想到二分L的长度,但是check合法性很麻烦。容易得出,如果用一个矩形包围所有点,那么长度为L的正方形的最优策略一定是位于矩形的四个角中的其中一个,枚举四个角,然后把位于小正方形内的点全部剔除,就变成了用两个小正方形覆盖所有点的子问题,于是用dfs直到第三层处理完后看是否涵盖所有点即可。

    一开始tmp数组和cnt开成了全局变量,导致dfs过程中会不断覆盖之前的值...调了好久

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 struct Node{
     5     int x,y;
     6 };
     7 Node a[20050];
     8 int vis[20050];
     9 
    10 void cut(int minx,int miny,int maxx,int maxy,int &cnt,int tmp[]){
    11     for (int i = 0;i < n;++i){
    12         if (a[i].x >= minx && a[i].x <= maxx && a[i].y >= miny && a[i].y <= maxy) {
    13             vis[i]++;
    14             tmp[cnt++] = i;
    15         }
    16     }
    17 }
    18 
    19 bool check(int L,int step){
    20     if (step == 3) {
    21         for (int i = 0;i < n;++i){
    22             if (!vis[i]) return false;
    23         }
    24         return true;
    25     }
    26     int minx,miny,maxx,maxy;
    27     minx = miny = 1e9+7;
    28     maxx = maxy = -1e9+7;
    29     for (int i = 0;i < n;++i){
    30         if (vis[i]) continue;
    31         minx = min(minx,a[i].x);
    32         miny = min(miny,a[i].y);
    33         maxx = max(maxx,a[i].x);
    34         maxy = max(maxy,a[i].y);
    35     }
    36 
    37     int cnt = 0,tmp[20050];
    38     cut(minx,miny,minx+L,miny+L,cnt,tmp);
    39     if (check(L,step+1)) return true;
    40     for (int i = 0;i < cnt;++i){
    41         vis[tmp[i]]--;
    42     }
    43 
    44     cnt = 0;
    45     cut(minx,maxy-L,minx+L,maxy,cnt,tmp);
    46     if (check(L,step+1)) return true;
    47     for (int i = 0;i < cnt;++i) vis[tmp[i]]--;
    48 
    49     cnt = 0;
    50     cut(maxx-L,maxy-L,maxx,maxy,cnt,tmp);
    51     if (check(L,step+1)) return true;
    52     for (int i = 0;i < cnt;++i) vis[tmp[i]]--;
    53 
    54     cnt = 0;
    55     cut(maxx-L,miny,maxx,miny+L,cnt,tmp);
    56     if (check(L,step+1)) return true;
    57     for (int i = 0;i < cnt;++i) vis[tmp[i]]--;
    58     return false;
    59 }
    60 
    61 
    62 int main(){
    63     scanf("%d",&n);
    64     for (int i = 0;i < n;++i){
    65         scanf("%d%d",&a[i].x,&a[i].y);
    66     }
    67     int l = 0;
    68     int r = 1e9+7;
    69     while(l < r){
    70         int mid = (l+r) >> 1;
    71         memset(vis,0,sizeof(vis));
    72         if (check(mid,0)) r = mid;
    73         else l = mid+1;
    74     }
    75     printf("%d
    ",l);
    76     return 0;
    77 }
  • 相关阅读:
    Wordpress 所有hoor列表
    Redis的PHP操作手册(转)
    thinkphp pathinfo nginx 无法加载模块:Index
    gitlab 创建SSH Keys 报500错
    在docker 中配置hadoop1.2.1 cluser
    docker 配置文件引发的问题
    shell在一个大文件找出想要的一段字符串操作技巧
    php关于金额比较引发的问题(转)
    mac 终端乱码
    Swoole笔记(二)
  • 原文地址:https://www.cnblogs.com/mizersy/p/9554308.html
Copyright © 2011-2022 走看看