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
4
0 1
0 -1
1 0
-1 0
0 1
0 -1
1 0
-1 0
Sample Output
1
HINT
首先可以确定此题满足可二分性,明显可以二分答案。所以我们只要能够在线性时间内检验即可了。
线性检测我们可以贪心解决,我们将每次还未被覆盖的点用一个最小的矩形来覆盖,然后每次选择用正方形覆盖它的四个角,总共递归三层,64种情况。所以我们枚举这64种情况,看是否能有一种能够覆盖所有的点。
这个贪心我开始没想到,现在也不会证明(理性想想是对的),我开始想的取左下角的点(x优先)为正方形左下角wa了,然后左下角的点(y优先)为正方形左下角wa了,再最左最下的两条平行坐标轴线的交点为正方形左下角还是wa了。最后将三者综合起来,还是wa了,但是正确率高了一些。这启发我以后贪心可以综合起来,取最优解正确率会高很多。
1 #include<vector> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cstdlib> 6 using namespace std; 7 8 #define inf (1<<29) 9 #define maxn 20010 10 int n,x[maxn],y[maxn]; bool exist[maxn]; 11 12 inline bool dfs(int L,int step,int all) 13 { 14 if (all == n) return true; 15 if (step > 3) return false; 16 int up = -inf,down = inf,le = inf,ri = -inf; 17 for (int i = 1;i <= n;++i) 18 if (!exist[i]) 19 { 20 up = max(y[i],up),down = min(y[i],down); 21 ri = max(x[i],ri),le = min(x[i],le); 22 } 23 int inc,nl,nr,nu,nd; vector <int> vec; 24 inc = 0; nl = le,nr = le+L,nu = up,nd = up-L; 25 for (int i = 1;i <= n;++i) 26 if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu) 27 ++inc,exist[i] = true,vec.push_back(i); 28 if (dfs(L,step+1,all+inc)) return true; 29 for (int i = 0;i < vec.size();++i) exist[vec[i]] = false; vec.clear(); 30 inc = 0; nl = le,nr = le+L,nu = down+L,nd = down; 31 for (int i = 1;i <= n;++i) 32 if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu) 33 ++inc,exist[i] = true,vec.push_back(i); 34 if (dfs(L,step+1,all+inc)) return true; 35 for (int i = 0;i < vec.size();++i) exist[vec[i]] = false; vec.clear(); 36 inc = 0; nl = ri-L,nr = ri,nu = up,nd = up-L; 37 for (int i = 1;i <= n;++i) 38 if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu) 39 ++inc,exist[i] = true,vec.push_back(i); 40 if (dfs(L,step+1,all+inc)) return true; 41 for (int i = 0;i < vec.size();++i) exist[vec[i]] = false; vec.clear(); 42 inc = 0; nl = ri-L,nr = ri,nu = down+L,nd = down; 43 for (int i = 1;i <= n;++i) 44 if (!exist[i] && x[i] >= nl&&x[i] <= nr&&y[i] >= nd&&y[i] <= nu) 45 ++inc,exist[i] = true,vec.push_back(i); 46 if (dfs(L,step+1,all+inc)) return true; 47 for (int i = 0;i < vec.size();++i) exist[vec[i]] = false; vec.clear(); 48 return false; 49 } 50 51 inline bool okay(int L) 52 { 53 memset(exist,false,n+1); 54 return dfs(L,1,0); 55 } 56 57 int main() 58 { 59 freopen("1052.in","r",stdin); 60 freopen("1052.out","w",stdout); 61 scanf("%d",&n); for (int i = 1;i <= n;++i) scanf("%d %d",&x[i],&y[i]); 62 if (okay(0)) printf("0"),exit(0); 63 int l = 1,r = inf,mid; 64 while (l <= r) 65 { 66 mid = (l + r) >> 1; 67 if (okay(mid)) r = mid - 1; 68 else l = mid + 1; 69 } 70 printf("%d",l); 71 fclose(stdin); fclose(stdout); 72 return 0; 73 }
高考结束,重新回归。