zoj 3717 2-SAT

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;
}







你可能感兴趣的:(zoj 3717 2-SAT)