BZOJ 1514 _ [POI2006]ZAB-Frogs 单调队列+二分BFS
来源:互联网 发布:php 生成订单号 编辑:程序博客网 时间:2024/05/18 17:42
题意:
给定一个网格图,其中有一些坏点,要求使起点到终点的路径上的所有点到离该点最近的坏点的最小距离距离最大,求这个最大值。
解析:
读完题显然分为两部分:
第一部分:预处理所有点到他最近的坏点的距离。
第二部分:二分最大距离bfs判定。
第二部分不用说吧?
主要就是卡在第一部分。
我们考虑按照每列来计算每个点的dis距离(即到他最近的坏点的距离)
显然可以发现,对于该列来说,每一行都可能有一个到该列最近的点,并且我们发现,如果某一行有两个坏点的话,假设分别为A,B,并且A到该列的距离最近,那么B显然不会对这一列的dis有任何影响。
所以我们显然可以在求之前预处理一下每一行的如果存在坏点的那个最近的坏点的坐标。
接下来,我们讨论坏点k,l,设我们要更新的点是(x,y)
如果k优于l,那么我们不妨列一下式子。
即
所以我们只需要按处理出来的坏点顺序维护一个
更新的时候每一次在其中二分查找最后一个<=2y的。
复杂度O(n*m*logn)
代码:
#include <queue>#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1100using namespace std;int n,m;int num;int calc[N][N];int xx[]={0,1,-1,0,0};int yy[]={0,0,0,-1,1};struct node{ int x,y; node(){} node(int _x,int _y):x(_x),y(_y){} friend istream& operator >> (istream &_,node &a) {scanf("%d%d",&a.x,&a.y);calc[a.y][++calc[a.y][0]]=a.x;return _;} friend bool operator == (node a,node b) {return a.x==b.x&&a.y==b.y;} node operator - (const node &a) {return node(x-a.x,y-a.y);} int operator * (const node &a) {return x*a.x+y*a.y;}}pt[N*N],st,ed;int dis[N][N];int f[N][N];node q[N];node newq[N];void init(){ for(int i=1;i<=m;i++) sort(calc[i]+1,calc[i]+calc[i][0]+1);}int get_dis(node a,node b){ return (a-b)*(a-b);}double q_calc(node a,node b,int tmpx){ return (double)(a.x*a.x-b.x*b.x+2*tmpx*b.x-2*tmpx*a.x)/(a.y-b.y)+a.y+b.y;}void get_min_dis(){ memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=num;i++) dis[pt[i].x][pt[i].y]=0; for(int i=1;i<=n;i++) { int l=1,r=0; for(int j=1;j<=m;j++) { int ll=1,rr=calc[j][0],ans=ll; while(ll<=rr) { int mid=(ll+rr)>>1; if(calc[j][mid]<=i)ans=mid,ll=mid+1; else rr=mid-1; } if(ans+1<=calc[j][0]&&abs(calc[j][ans+1]-i)<abs(calc[j][ans]-i)) ans++; if(ans<=calc[j][0]) { node tmp; tmp.x=calc[j][ans],tmp.y=j; q[++r]=tmp; } } if(r==1) { for(int j=1;j<=m;j++) dis[i][j]=get_dis(node(i,j),q[r]); continue; } int tmpr=r; l=1,r=0; for(int j=1;j<=tmpr;j++) { while(l<r&&q_calc(q[j],newq[r],i)<=q_calc(newq[r],newq[r-1],i))r--; if(l>=r||q_calc(q[j],newq[r],i)>q_calc(newq[r],newq[r-1],i)) newq[++r]=q[j]; } for(int j=1;j<=m;j++) { int ll=l+1,rr=r,ans=1; while(ll<=rr) { int mid=(ll+rr)>>1; if(q_calc(newq[mid],newq[mid-1],i)<=2*j)ans=mid,ll=mid+1; else rr=mid-1; } dis[i][j]=min(get_dis(node(i,j),newq[ans]),dis[i][j]); } } }bool check(int x){ memset(f,0,sizeof(f)); queue<node>que; if(dis[st.x][st.y]>=x) que.push(st),f[st.x][st.y]=1; while(!que.empty()) { node u=que.front(); que.pop(); for(int i=1;i<=4;i++) { node tmp; tmp.x=u.x+xx[i],tmp.y=u.y+yy[i]; if(tmp.x<=0||tmp.x>n||tmp.y<=0||tmp.y>m)continue; if(dis[tmp.x][tmp.y]>=x&&!f[tmp.x][tmp.y]) { f[tmp.x][tmp.y]=1; que.push(tmp); } } } return f[ed.x][ed.y];}int main(){ #ifndef ONLINE_JUDGE freopen("zab5ocen.in","r",stdin); freopen("1514.out","w",stdout); #endif scanf("%d%d",&n,&m); scanf("%d%d%d%d",&st.x,&st.y,&ed.x,&ed.y); scanf("%d",&num); for(int i=1;i<=num;i++)cin>>pt[i]; init(); get_min_dis(); int l=0,r=n*n+m*m,ans; while(l<=r) { int mid=(l+r)>>1; if(check(mid))l=mid+1,ans=mid; else r=mid-1; } printf("%d\n",ans); #ifndef ONLINE_JUDGE fclose(stdin);fclose(stdout); #endif return 0;}
0 0
- BZOJ 1514 _ [POI2006]ZAB-Frogs 单调队列+二分BFS
- 【单调栈 二分+BFS】【POI2006】ZAB-Frogs BZOJ1514
- bzoj1514: [POI2006]ZAB-Frogs
- BZOJ 1012 单调队列+二分
- bzoj 2792 [Poi2012]Well 单调队列 二分
- BZOJ 1510 [POI2006]Kra-The Disks 二分
- 【BZOJ】【P2096】【Poi2010】【Pilots】【题解】【二分+单调队列】
- BZOJ 3316 JC loves Mkk 二分答案+单调队列
- BZOJ 3885 Usaco2015 Jan Cow Rectangles 单调队列+二分
- BZOJ 3316: JC loves Mkk|单调队列|二分答案
- [二分答案 单调队列] BZOJ 3316 JC loves Mkk
- bzoj 2096: [Poi2010]Pilots (二分答案+单调队列)
- bzoj 3219: 巡游 (点分治+单调队列+二分)
- bzoj 4476: [Jsoi2015]送礼物 二分答案+单调队列
- [BZOJ]3316: JC loves Mkk 二分+单调队列
- bzoj 3316: JC loves Mkk(二分+单调队列)
- BZOJ 1047 单调队列
- BZOJ 4385 单调队列
- 在linux下用源代码编译MPICH 3.1.4
- IOS开发笔记-01按钮操作-13.上下左右移动 14.代码优化
- 数据挖掘工程师笔试及答案整理
- c语言之 switch 和 if 的使用比较(一)
- BZOJ 1512 [POI2006]Pro-Professor Szu Tarjan缩点+拓扑DP
- BZOJ 1514 _ [POI2006]ZAB-Frogs 单调队列+二分BFS
- BZOJ 1516 [POI2006]Mag-Warehouse 切比雪夫距离转曼哈顿距离
- 文本挖掘
- Java - socket双向通信例子
- Java-Socket通信 同时JSON传递与解析
- K-means
- linux由浅入深(10.1 )-- shell中的变量
- Java 开发 2.0: NoSQL
- Builder设计模式