n个事件,每个都要做出两种决策,二分一个半径,求这个半径下satifiable与否
坑爹的保证
“ You should promise that there is still no overlap for any two balloons after rounded.”
不能直接四舍五入
想到zzxx那时说的话才想起,不然肯定wa不止
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <cmath> using namespace std; #define N 210 #define eps 1e-6 double x[N][2],y[N][2],z[N][2]; int n; inline double cal_dist(int i,int ival,int j,int jval) { return (x[i][ival]-x[j][jval])*(x[i][ival]-x[j][jval])+ (y[i][ival]-y[j][jval])*(y[i][ival]-y[j][jval])+ (z[i][ival]-z[j][jval])*(z[i][ival]-z[j][jval]); } inline bool reach(int i,int ival,int j,int jval,double R) { return (x[i][ival]-x[j][jval])*(x[i][ival]-x[j][jval])+ (y[i][ival]-y[j][jval])*(y[i][ival]-y[j][jval])+ (z[i][ival]-z[j][jval])*(z[i][ival]-z[j][jval])<4*R*R; } vector<int>G[N*2]; bool mark[N*2]; int S[N*2],cnt; bool dfs(int x) { if(mark[x^1]) return false; if(mark[x]) return true; mark[x]=true; S[cnt++]=x; for(int i=0;i<G[x].size();++i) if(!dfs(G[x][i])) return false; return true; } // clause i = ival or j = jval void add_clause(int i,int ival,int j,int jval) { i=2*i+ival; j=2*j+jval; G[i^1].push_back(j); G[j^1].push_back(i); } bool solve(double R) { // initialize for(int i=0;i<=2*n;++i) G[i].clear(); memset(mark,false,sizeof(mark)); cnt=0; // build for(int i=0;i<n;++i) for(int a=0;a<2;++a) for(int j=i+1;j<n;++j) for(int b=0;b<2;++b) if(reach(i,a,j,b,R)) add_clause(i,a^1,j,b^1); // a,b can't be true at the same time, so a^1 or b^1 for(int i=0;i<2*n;i+=2) if(!mark[i]&&!mark[i^1]) { cnt=0; if(!dfs(i)) { while(cnt>0) mark[S[--cnt]]=false; if(!dfs(i^1)) return false; } } return true; } int main () { while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;++i) { for(int k=0;k<2;++k) scanf("%lf%lf%lf",&x[i][k],&y[i][k],&z[i][k]); } double left=0.0,right=0.0; double temp; for(int i=0;i<n;++i) for(int a=0;a<2;++a) for(int j=i+1;j<n;++j) for(int b=0;b<2;++b) { temp=sqrt(cal_dist(i,a,j,b))/2; if(right<temp) right=temp; } right+=1.0; while(right-left>eps) { double mid=(left+right)/2; if(solve(mid)) left=mid; else right=mid; } //left-=eps; printf("%.3lf\n",(int)(left*1000)/1000.0); } return 0; }