bzoj1052 覆盖问题 二分答案 dfs

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

题意:找到一个最小边长,使得以此为边长$3$个正方形可以覆盖平面上给定的一些点。

华丽爆零……

首先看到最小果断想二分答案……

然后我们证明一个东西……

首先,根据鸽巢原理,$3$个正方形覆盖由所有点构成的最小矩形一定有一个正方形是压着至少两条边的……

然后不外乎两种情况……

1、压的是对边,那么每个都在压对边,有一个正方形会压到三条边,就会压到一个角……

2、压的是邻边,一定会压到一个角……

那么方案就出来了……对于每个正方形,枚举压到了哪个角然后暴力排除每一个被覆盖的点……之后递归搜索新的矩形并继续……

问题得解……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=(int)1e6+5;
 7 int x[maxn],y[maxn],n,ax[4],ay[4],ajia[4],ajian[4];bool vis[maxn],now[4][maxn];int titai[3]={0,1,-1};
 8 bool dfs(int num,int val)
 9 {
10     if(num>3)
11     {
12         for(int i=1;i<=n;i++)
13             if(!vis[i])return 0;
14         return 1;
15     }
16     int maxx=-2147483647,minx=2147483647,maxy=-2147483647,miny=2147483647;
17     for(int i=1;i<=n;i++)
18         if(!vis[i])maxx=max(maxx,x[i]),minx=min(minx,x[i]),maxy=max(maxy,y[i]),miny=min(miny,y[i]);
19     if(max(maxx-minx,maxy-miny)<=val)return 1;
20     else if(num==3)return 0;
21     for(int i=1;i<=2;i++)
22         for(int j=1;j<=2;j++)
23         {
24             ajia[num]=titai[i],ajian[num]=titai[j];
25             if(ajia[num]==1&&ajian[num]==1)ax[num]=minx,ay[num]=miny;
26             else if(ajia[num]==1&&ajian[num]==-1)ax[num]=minx,ay[num]=maxy;
27             else if(ajia[num]==-1&&ajian[num]==1)ax[num]=maxx,ay[num]=miny;
28             else if(ajia[num]==-1&&ajian[num]==-1)ax[num]=maxx,ay[num]=maxy;
29             for(int i=1;i<=n;i++)
30                 if(!vis[i]&&((ajia[num]==1&&ajian[num]==1&&ax[num]<=x[i]&&ay[num]<=y[i]&&ax[num]+val>=x[i]&&ay[num]+val>=y[i])||(ajia[num]==1&&ajian[num]==-1&&ax[num]<=x[i]&&ay[num]>=y[i]&&ax[num]+val>=x[i]&&ay[num]-val<=y[i])||(ajian[num]==1&&ajia[num]==-1&&ay[num]<=y[i]&&ax[num]>=x[i]&&ay[num]+val>=y[i]&&ax[num]-val<=x[i])||(ajian[num]==-1&&ajia[num]==-1&&ay[num]>=y[i]&&ax[num]>=x[i]&&ay[num]-val<=y[i]&&ax[num]-val<=x[i])))vis[i]=now[num][i]=1;
31             int t=dfs(num+1,val);
32             for(int i=1;i<=n;i++)if(now[num][i])vis[i]=now[num][i]=0;
33             if(t)return 1;
34         }
35     return 0;
36 }
37 bool check(int val)
38 {
39     return dfs(1,val);
40 }
41 int haha()
42 {
43     scanf("%d",&n);int maxx=-2147483647,minx=2147483647,maxy=-2147483647,miny=2147483647;
44     for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]),maxx=max(maxx,x[i]),minx=min(minx,x[i]),maxy=max(maxy,y[i]),miny=min(miny,y[i]);
45     int l=1,r=max(maxx-minx,maxy-miny),mid;
46     while(l<=r)
47     {
48         mid=(l+r)>>1;
49         if(check(mid))r=mid-1;
50         else l=mid+1;
51     }
52     printf("%d\n",l);
53 }
54 int sb=haha();
55 int main(){;}
bzoj1052

 

posted @ 2017-09-22 16:45  ccc000111  阅读(270)  评论(0编辑  收藏  举报