BZOJ 1052 覆盖问题
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
0 1
0 -1
1 0
-1 0
Sample Output
HINT
首先可以确定此题满足可二分性,明显可以二分答案。所以我们只要能够在线性时间内检验即可了。
线性检测我们可以贪心解决,我们将每次还未被覆盖的点用一个最小的矩形来覆盖,然后每次选择用正方形覆盖它的四个角,总共递归三层,64种情况。所以我们枚举这64种情况,看是否能有一种能够覆盖所有的点。
这个贪心我开始没想到,现在也不会证明(理性想想是对的),我开始想的取左下角的点(x优先)为正方形左下角wa了,然后左下角的点(y优先)为正方形左下角wa了,再最左最下的两条平行坐标轴线的交点为正方形左下角还是wa了。最后将三者综合起来,还是wa了,但是正确率高了一些。这启发我以后贪心可以综合起来,取最优解正确率会高很多。
- #include<vector>
- #include<iostream>
- #include<cstring>
- #include<cstdio>
- #include<cstdlib>
- using namespace std;
- #define inf (1<<29)
- #define maxn 20010
- int n,x[maxn],y[maxn]; bool exist[maxn];
- inline bool dfs(int L,int step,int all)
- {
- if (all == n) return true;
- if (step > ) return false;
- int up = -inf,down = inf,le = inf,ri = -inf;
- for (int i = ;i <= n;++i)
- if (!exist[i])
- {
- up = max(y[i],up),down = min(y[i],down);
- ri = max(x[i],ri),le = min(x[i],le);
- }
- int inc,nl,nr,nu,nd; vector <int> vec;
- inc = ; nl = le,nr = le+L,nu = up,nd = up-L;
- for (int i = ;i <= n;++i)
- if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu)
- ++inc,exist[i] = true,vec.push_back(i);
- if (dfs(L,step+,all+inc)) return true;
- for (int i = ;i < vec.size();++i) exist[vec[i]] = false; vec.clear();
- inc = ; nl = le,nr = le+L,nu = down+L,nd = down;
- for (int i = ;i <= n;++i)
- if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu)
- ++inc,exist[i] = true,vec.push_back(i);
- if (dfs(L,step+,all+inc)) return true;
- for (int i = ;i < vec.size();++i) exist[vec[i]] = false; vec.clear();
- inc = ; nl = ri-L,nr = ri,nu = up,nd = up-L;
- for (int i = ;i <= n;++i)
- if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu)
- ++inc,exist[i] = true,vec.push_back(i);
- if (dfs(L,step+,all+inc)) return true;
- for (int i = ;i < vec.size();++i) exist[vec[i]] = false; vec.clear();
- inc = ; nl = ri-L,nr = ri,nu = down+L,nd = down;
- for (int i = ;i <= n;++i)
- if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu)
- ++inc,exist[i] = true,vec.push_back(i);
- if (dfs(L,step+,all+inc)) return true;
- for (int i = ;i < vec.size();++i) exist[vec[i]] = false; vec.clear();
- return false;
- }
- inline bool okay(int L)
- {
- memset(exist,false,n+);
- return dfs(L,,);
- }
- int main()
- {
- freopen("1052.in","r",stdin);
- freopen("1052.out","w",stdout);
- scanf("%d",&n); for (int i = ;i <= n;++i) scanf("%d %d",&x[i],&y[i]);
- if (okay()) printf(""),exit();
- int l = ,r = inf,mid;
- while (l <= r)
- {
- mid = (l + r) >> ;
- if (okay(mid)) r = mid - ;
- else l = mid + ;
- }
- printf("%d",l);
- fclose(stdin); fclose(stdout);
- return ;
- }
BZOJ 1052 覆盖问题的更多相关文章
- [BZOJ]1052 覆盖问题(HAOI2007)
三矩形覆盖问题啊……不过听说FJOI还出过双圆覆盖问题? Description 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来, ...
- BZOJ 1052: [HAOI2007]覆盖问题
BZOJ 1052: [HAOI2007]覆盖问题 题意:给定平面上横纵坐标在-1e9~1e9内的20000个整数点的坐标,用三个大小相同边平行于坐标轴的正方形覆盖(在边界上的也算),问正方形的边长最 ...
- 二分判定 覆盖问题 BZOJ 1052
//二分判定 覆盖问题 BZOJ 1052 // 首先确定一个最小矩阵包围所有点,则最优正方形的一个角一定与矩形一个角重合. // 然后枚举每个角,再解决子问题 #include <bits/s ...
- 【BZOJ 1052】 1052: [HAOI2007]覆盖问题 (乱搞)
1052: [HAOI2007]覆盖问题 Description 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄 膜把这些小树遮盖起来,经过一番长久的 ...
- AC日记——[HAOI2007]覆盖问题 bzoj 1052
1052 思路: 二分答案: 二分可能的长度: 然后递归判断长度是否可行: 先求出刚好覆盖所有点的矩形: 可行的第一个正方形在矩形的一个角上: 枚举四个角上的正方形,然后删去点: 删去一个正方形后,递 ...
- [BZOJ 1052][HAOI2007]覆盖问题(二分答案)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1052 分析: 挺有想法的一道题,先二分答案ans,主要是判断的问题. 首先可以弄出把所 ...
- BZOJ 1052 HAOI2007 覆盖问题 二分法答案+DFS
标题效果:特定n点.涵盖所有的点与同方三面.斧头要求方垂直边界,最小平方的需求方长值 最大值至少.答案是很明显的二分法 但验证是一个问题 考虑仅仅有三个正方形,故用一个最小矩形覆盖这三个正方形时至少有 ...
- 【以前的空间】bzoj 1052 [HAOI2007]覆盖问题
这道题的思路挺简单的……就是可以证明如果要覆盖一个区域内的点,那么一定有一个正方形在这“区域内的点所围成的最大矩形的四个角中的一个”(不要吐槽很多的“的”……),对于长度r是否可以覆盖整个区域内的点, ...
- bzoj 1052 dfs
首先可以二分答案,将最优性问题转化为判定性问题. 对于二分到的边长,我们可以把所有的点看成一个大的矩形,这个矩形为包括所有点的最小矩形,那么贪心的想,3个正方形,第一个肯定放在这个矩形其中的一角,然后 ...
随机推荐
- android 回车键事件编程
实现android按下回车键便隐藏输入键盘,有两种方法: 1.)如果布局是多个EditText,为每个EditText控件设置android:singleLine=”true”,弹出的软盘输入法中回车 ...
- 你需要知道的 Android 拍照适配方案
近段时间,家里陪自己度过大学四年的电脑坏了,挑选好的新电脑配件终于在本周全部到货,自己动手完成组装.从AMD到i7的CPU,6G内存到14G内存,打开 AndroidStudio 的速度终于杠杆的上去 ...
- Programming a Spider in Java 源码帖
Programming a Spider in Java 源码帖 Listing 1: Finding the bad links (CheckLinks.java) import java.awt. ...
- CUDA与VS2013安装
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- DataTable和List集合互转
/// <summary> /// 将集合转换成DataTable /// </summary> /// <param name="list"> ...
- [原创] SQLite数据库使用清单(上)
1. 介绍 1.1 安装 访问 SQLite 下载页面,从 Windows 区下载预编译的二进制文件. 您需要下载 sqlite-shell-win32-*.zip 和 sqlite-dll-win3 ...
- Android 4.0及以上版本接收开机广播BOOT_COMPLETED、开机自启动服务
1.BootCompletedReceiver.Java文件 public class BootCompletedReceiver extends BroadcastReceiver { @Overr ...
- VS2015 Cordova Ionic移动开发(五)
一.创建侧边菜单和导航项目 1.使用VS创建一个Ionic空项目,同时创建一个Ionic SideMenu和Ionic Tabs项目.将SideMenu和Tabs项目里的templates和js文件合 ...
- [转帖]音响及DarBee
红外与蓝牙的差别 1.距离 红外:对准.直接.1—2米,单对单 红外线可以用你的手机摄像头看到 蓝牙:10米左右,可加强信号,可以绕弯,可以不对准,可以不在同一间房间,链接最大数目可达7个,同时区分 ...
- oracle安装遇到的问题
这两天要做一个项目,教师招聘系统.要用oracle.就安装了oracle 12c,安装的过程中遇到了一些问题,最后自己解决了.我是win7系统. 第一个报错: [INS-30131]执行安装程序验证所 ...