首页 > 代码库 > ZOJ 3717

ZOJ 3717

这题是二分+2SAT.

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

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

  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