这题是二分+2SAT.

总结一下SAT题的特征。首先,可能会存在二选一的情况,然后会给出一些矛盾。据这些矛盾加边,再用SAT判定。

这一道题好像不能直接用printf("%0.3lf"),因为这个是四舍五入的,这道题好像不能四舍五入,只好选减去0.0005再按这个格式输出了。

ZOJ 3717_四舍五入ZOJ 3717_i++_02
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <stdlib.h>
  7 #define oo 1000000007
  8 #define eps 1e-4
  9 using namespace std;
 10 const int MAXN=420;
 11 const int MAXM=320000;
 12 struct b{
 13     int x,y,z;
 14 }ball[MAXN];
 15 double dis[MAXN][MAXN];
 16 int head[MAXN],dfn[MAXN],low[MAXN],tot,stop,indx,belong[MAXN],pat;
 17 int st[MAXN];
 18 bool stack[MAXN];
 19 int n;
 20 struct e{
 21     int u,v;
 22     int next;
 23 }edge[MAXM];
 24 
 25 void addedge(int u,int v){
 26     edge[tot].u=u;
 27     edge[tot].v=v;
 28     edge[tot].next=head[u];
 29     head[u]=tot++;
 30 }
 31 
 32 void tarjan(int u){
 33     int v;
 34     dfn[u]=low[u]=++indx;
 35     st[stop++]=u;
 36     stack[u]=true;
 37     for (int e=head[u];e!=-1;e=edge[e].next){
 38         v=edge[e].v;
 39         if (dfn[v]==0) {
 40             tarjan(v) ;
 41             low[u] = min(low[u], low[v]) ;
 42         }
 43         else if (stack[v]) { 
 44             low[u] = min(low[u], dfn[v]) ;
 45         }
 46     }
 47     if (dfn[u] == low[u]) {
 48         pat++;
 49         do{ 
 50             v = st[--stop];
 51             belong[v]=pat;
 52             stack[v]=false;
 53         }while(u!= v); 
 54     } 
 55 }
 56 
 57 bool slove(double leng){
 58     int a,b; tot=0; indx=0; stop=0; pat=-1;
 59     memset(head,-1,sizeof(head));
 60     for(int i=0;i<n;i++){
 61         a=i;
 62         for(int j=i+1;j<n;j++){
 63             b=j;
 64             if(leng*2>dis[a*2][b*2]){
 65                 addedge(2*a+1,b*2);
 66                 addedge(b*2+1,a*2);
 67             }
 68             if(leng*2>dis[a*2][b*2+1]){
 69                 addedge(a*2+1,b*2+1);
 70                 addedge(b*2,a*2);
 71             }
 72             if(leng*2>dis[a*2+1][b*2]){
 73                 addedge(a*2,b*2);
 74                 addedge(b*2+1,a*2+1);
 75             }
 76             if(leng*2>dis[a*2+1][b*2+1]){
 77                 addedge(a*2,b*2+1);
 78                 addedge(b*2,a*2+1);
 79             }
 80         }
 81     }
 82     memset(dfn,0,sizeof(dfn));
 83     memset(low,0,sizeof(low));
 84     memset(stack,false,sizeof(stack));
 85     memset(belong,-1,sizeof(belong));
 86     for(int i=0;i<2*n;i++){
 87         if(dfn[i]==0){
 88             tarjan(i);
 89         }
 90     }
 91     bool flag=true;
 92     for(int i=0;i<n;i++){
 93         if(belong[i*2]==belong[i*2+1]){
 94             flag=false;
 95             break;
 96         }
 97     }
 98     return flag;
 99 }
100 
101 int main(){
102     double xi,yi,zi;
103     while(scanf("%d",&n)!=EOF){
104         for(int i=0;i<2*n;i++){
105             scanf("%d%d%d",&ball[i].x,&ball[i].y,&ball[i].z);
106             i++;
107             scanf("%d%d%d",&ball[i].x,&ball[i].y,&ball[i].z);
108         }
109         double high=oo,lown=0; double tmp;
110         for(int i=0;i<2*n;i++){
111             for(int j=i;j<2*n;j++){
112                 xi=ball[i].x-ball[j].x;
113                 yi=ball[i].y-ball[j].y;
114                 zi=ball[i].z-ball[j].z;
115                 tmp=sqrt(xi*xi+yi*yi+zi*zi);
116                 dis[i][j]=dis[j][i]=tmp;
117             }
118         }
119         double ans;
120         while(lown<high-eps){
121             double mid=(high+lown)/2;
122             if(slove(mid)){
123                 ans=mid;
124                 lown=mid;
125             }
126             else high=mid;
127         }
128         printf("%0.3lf\n",ans-0.0005);
129     }
130     return 0;
131 }
View Code