给出一些点对,你可以在每对中任意选一个,只能选一个,放置一个炸弹,每个炸弹爆炸时都有一个效果范围,会波及到其放置点为圆心,半径为 r 的圆的范围,问如果要让任意两个圆都不相交(可以相切)的话,半径的最大值是多少。
很裸的 2-SAT 模型,每组点分为 A 和 A‘ ,然后2分枚举半径的值,如果两点间距离小于半径的二倍,那么这两点不能同时放置炸弹,也就是说他们矛盾,根据这个关系建边,判断是否存在解,如果存在说明半径还可以继续增大,否则,半径要减小。
PS:这个题的精度问题,输出要求的是10的负二次方,但是精度只开到 1e-3 会wa,1e-4 就可以过了。
#include<cstdio> #include<cstring> #include<stack> #include<cmath> using namespace std; const double eps = 1e-4; const int N = 210; struct point{ double x,y; }; int dcmp(double x)//判断参数的符号,负数返回-1,0返回0,正数返回1 { if (x < -eps) return -1; else return x > eps; } double dis(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } struct Edge{ int s,e,next; }edge[N*N]; int m,e_num,vis_num,cnt,head[N],instack[N],low[N],tim[N],belong[N]; void AddEdge(int a,int b){ edge[e_num].s=a; edge[e_num].e=b; edge[e_num].next=head[a]; head[a]=e_num++; } stack <int>st; void tarjan(int x){ int i; tim[x]=low[x]=++vis_num; instack[x]=1; st.push(x); for(i=head[x];i!=-1;i=edge[i].next){ int u=edge[i].e; if(tim[u]==-1){ tarjan(u); if(low[x]>low[u])low[x]=low[u]; } else if(instack[u] && low[x]>tim[u])low[x]=tim[u]; } if(low[x]==tim[x]){ cnt++; do{ i=st.top(); st.pop(); instack[i]=0; belong[i]=cnt; }while(i!=x); } } void init(){ vis_num=cnt=0; memset(instack,0,sizeof(instack)); memset(belong,-1,sizeof(belong)); memset(tim,-1,sizeof(tim)); memset(low,0,sizeof(low)); } int main() { int i,j; double left,right,mid,ans; point pa[N],pb[N]; while(~scanf("%d",&m)) { for(i=0;i<m;i++) scanf("%lf%lf%lf%lf",&pa[i].x,&pa[i].y,&pb[i].x,&pb[i].y); double max=-1.0; for(i=0;i<m;i++){ for(j=i+1;j<m;j++){ if(dcmp( dis(pa[i],pa[j])-max )==1)max=dis(pa[i],pa[j]); if(dcmp( dis(pb[i],pb[j])-max )==1)max=dis(pb[i],pb[j]); if(dcmp( dis(pa[i],pb[j])-max )==1)max=dis(pa[i],pb[j]); if(dcmp( dis(pb[i],pa[j])-max )==1)max=dis(pb[i],pa[j]); } } left=0.0; right=max; while(dcmp(left-right)==-1){ mid=(left+right)/2; e_num=0; memset(head,-1,sizeof(head)); for(i=0;i<m;i++){ for(j=i+1;j<m;j++){ if(dcmp( dis(pa[i],pa[j])-2*mid )==-1){ AddEdge(2*i,2*j+1); AddEdge(2*j,2*i+1); } if(dcmp( dis(pa[i],pb[j])-2*mid )==-1){ AddEdge(2*i,2*j); AddEdge(2*j+1,2*i+1); } if(dcmp( dis(pb[i],pa[j])-2*mid )==-1){ AddEdge(2*i+1,2*j+1); AddEdge(2*j,2*i); } if(dcmp( dis(pb[i],pb[j])-2*mid )==-1){ AddEdge(2*i+1,2*j); AddEdge(2*j+1,2*i); } } } init(); for(i=0;i<2*m;i++){ if(tim[i]==-1)tarjan(i); } int flag=1; for(i=0;i<m;i++){ if(belong[2*i]==belong[2*i+1]){ flag=0;break; } } if(flag){ ans=mid; left=mid+eps; } else right=mid-eps; } printf("%.2lf\n",ans); } return 0; }