A nxn grid floor has some laser beams vertically directed from the ceiling to a grid on the ground. A circle needs to safely move from left to right without hitting the upper boundary, lower boundary, and laser beam, ask the maximum diameter of the circle.
Analysis: Binary diameter is supported. The key lies in the checking function. It can be said that this circle is reduced to a point, and the diameter of the circle is converted to the scanning range of the laser. When the laser range completely blocks a channel, this diameter is not feasible. How can we determine whether a channel is blocked. During each check (DIS), the laser beam pair is enumerated. if the distance between the laser beam is smaller than DIS, an edge is created between the two. Also pay attention to processing the border. If the laser beam range and the upper or lower boundary intersect, then the boundary and the laser beam also create an edge. Finally, from a boundary DFS to another boundary, if it can be DFS, it means that the channel is blocked at this time, and this dis cannot. You can get the answer by adding two points.
Code:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <string>#include <vector>using namespace std;#define N 5007struct node{ int x,y;}p[N];double d[N][N];vector<int> G[N];int n,L;int vis[N],S,E;double dis(node ka,node kb){ return (double)sqrt((ka.x-kb.x)*(ka.x-kb.x)+(ka.y-kb.y)*(ka.y-kb.y));}int dfs(int u,int fa){ if(u == E) return 1; vis[u] = 1; for(int i=0;i<G[u].size();i++) { int v = G[u][i]; if(v == fa) continue; if(vis[v]) continue; if(dfs(v,u)) return 1; } return 0;}bool check(double D){ S = 0; E = L+1; for(int i=0;i<=L+1;i++) G[i].clear(); for(int i=1;i<=L;i++) { if(p[i].y < D) G[S].push_back(i); if(p[i].y + D > n) G[i].push_back(E); for(int j=i+1;j<=L;j++) { if(d[i][j] < D) { G[i].push_back(j); G[j].push_back(i); } } } memset(vis,0,sizeof(vis)); if(dfs(S,-1)) return 0; return 1;}int main(){ int i,j; while(scanf("%d%d",&n,&L)!=EOF && n) { for(i=1;i<=L;i++) scanf("%d%d",&p[i].x,&p[i].y); for(i=1;i<=L;i++) for(j=i+1;j<=L;j++) d[i][j] = dis(p[i],p[j]); double low = eps; double high = n; while(low+eps < high) { double mid = (low+high)/2.0; if(check(mid)) low = mid; else high = mid; } printf("%.3lf\n",low); } return 0;}
View code