• BZOJ_1052_[HAOI2007]_覆盖问题_(二分+贪心)


    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=1052

    网格图,给出(n)个点,要求用3个边长相同的正方形覆盖所有点,求最小边长.

    分析


    显然是二分+判断可行性.

    如何判断可行性呢?我们注意到是3个正方形.为什么是3个?

    我们先找出覆盖所有点的最小距形,那么距形的四条边必须有正方形贴着,而又是3个正方形,所以至少要有1个正方形同时贴着两条边.

    1.贴着的边相对

    这样的话三个正方形都同时贴着相对的两条边,比如是上下两条边,那么贴着左边的那个正方形就贴着3条边,在距形的一角.

    2.贴着的边相邻

    这样的话这个正方形就在距形的一角.

    所以我们递归的把正方形放在距形的一角,然后去掉已经覆盖了的点,继续放正方形即可.

     1 #include <bits/stdc++.h>
     2 #define fst first
     3 #define scd second
     4 using namespace std;
     5 inline int read(int &x){x=0;int k=1;char c;for(c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')k=-1;for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';return x*=k;}
     6 
     7 typedef pair <int,int> P;
     8 const int maxn=20000+5,INF=0x7fffffff;
     9 int n,ml,mr,mu,md;
    10 P a[maxn];
    11 bool vis[maxn];
    12 bool dfs(int x,int t){
    13     if(t==3) return max(md-mu,mr-ml)<=x;
    14     P b[4][2];
    15     b[0][0]=P(ml,mu),b[0][1]=P(ml+x,mu+x);
    16     b[1][0]=P(ml,md-x),b[1][1]=P(ml+x,md);
    17     b[2][0]=P(mr-x,mu),b[2][1]=P(mr,mu+x);
    18     b[3][0]=P(mr-x,md-x),b[3][1]=P(mr,md);
    19     for(int i=0;i<4;i++){
    20         int tl=ml,tr=mr,tu=mu,td=md;
    21         int tmp[maxn];
    22         for(int j=1;j<=n;j++) tmp[j]=vis[j];
    23         for(int j=1;j<=n;j++)
    24                 if(a[j].fst>=b[i][0].fst&&a[j].fst<=b[i][1].fst&&a[j].scd>=b[i][0].scd&&a[j].scd<=b[i][1].scd)
    25                     vis[j]=true;
    26         mu=ml=INF; mr=md=-INF;
    27         for(int j=1;j<=n;j++)if(!vis[j]){
    28             mu=min(mu,a[j].scd); md=max(md,a[j].scd);
    29             ml=min(ml,a[j].fst); mr=max(mr,a[j].fst);
    30         }
    31         bool flag=dfs(x,t+1);
    32         ml=tl,mr=tr,mu=tu,md=td;
    33         for(int j=1;j<=n;j++) vis[j]=tmp[j];
    34         if(flag) return true;
    35     }
    36     return false;
    37 }
    38 inline void solve(){
    39     int l=0,r=max(md-mu,mr-ml);
    40     while(l<r){
    41         for(int i=1;i<=n;i++)if(vis[i]) puts("!");
    42         int mid=l+(r-l)/2;
    43         if(dfs(mid,1)) r=mid;
    44         else l=mid+1;
    45     }
    46     printf("%d
    ",l);
    47 }
    48 inline void init(){
    49     read(n);
    50     mu=ml=INF,mr=md=-INF;
    51     for(int i=1;i<=n;i++){
    52         read(a[i].fst), read(a[i].scd);
    53         ml=min(ml,a[i].fst); mr=max(mr,a[i].fst);
    54         mu=min(mu,a[i].scd); md=max(md,a[i].scd);
    55     }
    56 }
    57 int main(){
    58     init();
    59     solve();
    60     return 0;
    61 }
    View Code

    1052: [HAOI2007]覆盖问题

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1540  Solved: 705
    [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

    Source

  • 相关阅读:
    【BigData】Java基础_ArrayList的使用
    【BigData】Java基础_构造方法的使用
    【BigData】Java基础_类和对象的基本使用
    【BigData】Java基础_冒泡排序
    【BigData】Java基础_数组
    【BigData】Java基础_循环
    【BigData】Java基础_终端输入2个数字并求和
    Navicat自动断开连接处理方式
    名字修饰约定extern "C"与extern "C++"浅析
    qt study 元对象,属性和反射编程
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5649055.html
Copyright © 2020-2023  润新知