zoj 3717 - Balloon(2-SAT)

裸的2-SAT,详见刘汝佳训练指南P-323

不过此题有个特别需要注意的地方:You should promise that there is still no overlap for any two balloons after rounded.

模版题,

代码如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>

#define LL long long
#define eps 1e-5
#define M 205
#define mod 1000000007

using namespace std;

struct Point
{
    int x, y, z;
    Point() { }
    Point(int x, int y, int z) : x(x), y(y), z(z) { }
    void readPoint()
    {
        scanf("%d %d %d", &x, &y, &z);
    }
};
struct TwoSAT
{
    int n;
    vector<int>G[M*2];
    bool mark[M*2];
    int S[M*2], c;

    bool dfs(int x)
    {
        if(mark[x^1]) return false;
        if(mark[x]) return true;
        mark[x] = true;
        S[c++] = x;
        for(int i = 0; i < (int)G[x].size(); ++i)
            if(!dfs(G[x][i])) return false;
        return true;
    }

    void init(int n)
    {
        this->n = n;
        for(int i = 0; i < n*2; ++i)    G[i].clear();
        memset(mark, 0, sizeof(mark));
    }

    void add_clause(int x, int y)
    {
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }

    bool solve()
    {
        for(int i = 0; i < n*2; i+=2)
            if(!mark[i] && !mark[i+1])
            {
                c = 0;
                if(!dfs(i))
                {
                    while(c>0) mark[S[--c]] = false;
                    if(!dfs(i+1)) return false;
                }
            }
        return true;
    }
};
Point poi[2*M];
int dcmp(double a)
{
    if(fabs(a)<eps) return 0;
    return a<0?-1:1;
}
double dis(Point a, Point b)
{
    return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y)+1.0*(a.z-b.z)*(a.z-b.z));
}
int ok(int n, double R)
{
    TwoSAT temp;
    temp.init(n);
    for(int i = 0; i < 2*n; ++i)
        for(int j = i+1; j < 2*n; ++j)
            if(dcmp(dis(poi[i], poi[j])-2*R)<0)
            {
                temp.add_clause(i^1, j^1);
            }
    return temp.solve();
}
int main ()
{
    int n;
    while(~scanf("%d", &n))
    {
        for(int i = 0; i < 2*n; ++i)
            poi[i].readPoint();
        double l = 0.0, r = dis(Point(0,0,0), Point(10000,10000,10000)), mid;
        while(r-l>eps)
        {
            mid = (r+l)/2;
            if(ok(n, mid))
                l = mid;
            else
                r = mid;
        }
        double ans = (int)(mid*1000+0.5)/1000.0;//注意!!!
        if(!ok(n, ans)) ans-=0.001;
        printf("%.3lf\n", ans);
    }
    return 0;
}


posted on 2013-08-20 08:56  Primo...  阅读(284)  评论(0编辑  收藏  举报