2 1 1 1 -1 -1 -1 -1 1 2 1 1 -1 -1 1 -1 -1 1
1.41 1.00
题目大意:一个平面内给n对点,每对点只能放一个炸弹,每个炸弹杀伤以该炸弹为中心的一个圆形区域,每个炸弹杀伤范围相同,杀伤半径任意。现在要求任意2个炸弹杀伤范围不重叠,求炸弹最大杀伤半径。
题目分析:要求杀伤半径,半径范围不超过3000,于是选择二分半径,然后枚举任意两对点之间的相互位置关系,与杀伤半径相比,建图,跑一遍2-SAT找矛盾。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstdlib> #include<cmath> using namespace std; const int N = 205; const int M = 40005; const double eps = 1e-5; double tb[105][105][4]; struct point { int x1,x2,y1,y2; }pt[105]; struct edge { int to,next; }g[M]; int head[N]; int scc[N]; bool flag; int vis[N]; int stack1[N]; int stack2[N]; int n; int num; void init() { memset(head,-1,sizeof(head)); memset(scc,0,sizeof(scc)); memset(vis,0,sizeof(vis)); flag = true; num = 0; stack1[0] = stack2[0] = 0; } void build(int s,int t) { g[num].to = t; g[num].next = head[s]; head[s] = num ++; } double dis(double x1,double y1,double x2,double y2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } void maketable() { int i,j; for(i = 1;i < n;i ++) { for(j = i + 1;j <= n;j ++) { tb[i][j][0] = dis(pt[i].x1,pt[i].y1,pt[j].x1,pt[j].y1); tb[i][j][1] = dis(pt[i].x1,pt[i].y1,pt[j].x2,pt[j].y2); tb[i][j][2] = dis(pt[i].x2,pt[i].y2,pt[j].x1,pt[j].y1); tb[i][j][3] = dis(pt[i].x2,pt[i].y2,pt[j].x2,pt[j].y2); } } } void dfs(int cur,int &sig,int &cnt) { if(!flag) return; vis[cur] = ++sig; stack1[++stack1[0]] = cur; stack2[++stack2[0]] = cur; for(int i = head[cur];i != -1;i = g[i].next) { if(!vis[g[i].to]) dfs(g[i].to,sig,cnt); else { if(scc[g[i].to] == 0) { while(vis[stack2[stack2[0]]] > vis[g[i].to]) stack2[0] --; } } } if(stack2[stack2[0]] == cur) { ++cnt; stack2[0] --; do { scc[stack1[stack1[0]]] = cnt; int tmp = stack1[stack1[0]]; if(tmp > n) { if(scc[tmp - n] && scc[tmp - n] == cnt) { flag = false; return; } } else { if(scc[tmp + n] && scc[tmp + n] == cnt) { flag = false; return; } } }while(stack1[stack1[0] --] != cur); } } bool Gabow() { int i,sig,cnt; sig = cnt = 0; for(i = 1;i <= n + n && flag;i ++) if(!vis[i]) dfs(i,sig,cnt); return flag; } int main() { int i,j; while(scanf("%d",&n) != EOF) { for(i = 1;i <= n;i ++) { scanf("%d%d%d%d",&pt[i].x1,&pt[i].y1,&pt[i].x2,&pt[i].y2); } maketable(); double l,r,mid; l = 0.0; r = 30000.0; double ans; while(r - l > eps) { mid = (l + r) / 2; init(); for(i = 1;i < n;i ++) { for(j = i + 1;j <= n;j ++) { if(tb[i][j][0] - mid < eps)//i j { build(i,j + n); build(j,i + n); } if(tb[i][j][1] - mid < eps)//i j + n { build(i,j); build(j + n,i + n); } if(tb[i][j][2] - mid < eps)//i + n j { build(i + n,j + n); build(j,i); } if(tb[i][j][3] - mid < eps) { build(i + n,j); build(j + n,i); } } } if(Gabow()) { ans = mid; l = mid; } else r = mid; } printf("%.2lf\n",ans/2); } return 0; } //140MS 868K