Chieh's Blog

Because Of Coding

ZOJ Problem Set - 3717 Balloon

Chieh posted @ 2015年1月04日 23:33 in ZOJ , 358 阅读

飞机票: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5040

从这一题我对2-sat有更深的了解了。。。起先以为2-sat要添加一定可行的边。。。其实不然。。。要求添加可能可以的边。。。意思就是说两个组每个组2个人A1 A2,B1,B2 如果A1选了不能选B1,那么不管A2选了能不能选B1。。。都添加A2 B1这条边搞了一天2-sat 什么鬼~~~反正现在深入了解了。。。好了。。直接正题~~~

分析。。这题就是说给你n个组。每个组有两个球。。每个球有坐标。。从每个组里选择一个球。。且所有球不重叠。。。球最大球径是多少。。。其实就是2-sat问题。。。怎么搞呢??先求出每队之间的距离。。。即一共有四个距离。。。即(A1,B1),(A1,B2),(A2,B1),(A2,B2) 三维距离很简单。。。((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)^0.5即可。。搜噶然后二分球径。。。这里可以剪下枝。。。怎么搞呢。。。先从上面的距离选出最大的距离作为r,l为0。。。然后在循环里面可以判断下那四个距离是否都小于R,如果小于R。。则不符合条件。。直接继续二分。。。如果有一个可以则。。。根据2-sat建边。。。这里得知道要添加可能的边(起先不知道。。Wa到死)一共有四种可能。。所以有4种添边方案。。。然后每次二分跑一下tarjan。。。如果符合条件。。则l变为mid+e...这里e是定义的精度。。。如果不可以。。那r就要变为mid-e...当可行的时候。。。可以定义一个double记录最大符合条件的球径。。。其实起先我还卡了一下为什么距离要跟球径的两倍比较。。。后来想了一下球可以转的啊。。。太菜了。。。最后精度又是个问题。。。但是只要保留4位小数就可以了。。。因为是spj。。。然后啪啪啪!!!AC!!!

/*
Author:Chieh
Grow up happy
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define LL long long
using namespace std;
const int maxn=456;
const double e=0.0001;
struct he
{
    int a,b,c;
} JLJ[maxn];
vector<int> V[maxn];
double dist[maxn][maxn];
int n;
void init()
{
    for(int i=0; i<n; i++)
    {
        scanf("%d%d%d",&JLJ[i*2].a,&JLJ[i*2].b,&JLJ[i*2].c);
        scanf("%d%d%d",&JLJ[i*2+1].a,&JLJ[i*2+1].b,&JLJ[i*2+1].c);
    }

}
bool instack[maxn];
int dfn[maxn],low[maxn],sta[maxn],belong[maxn],indexx,scnt,cntnum;
void tarjan(int u)
{
    dfn[u]=low[u]=indexx++;
    instack[u]=1;
    sta[++scnt]=u;
    for(int i=0; i<V[u].size(); i++)
    {

        int v=V[u][i];
        if(dfn[v]==-1)
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])low[u]=min(dfn[v],low[u]);
    }
    if(dfn[u]==low[u])
    {
        for(int v=-1; v!=u; scnt--)
        {
            v=sta[scnt];
            instack[v]=0;
            belong[v]=cntnum;
        }
        cntnum++;
    }
}
double cal(double a,double b,double c,double d,double e,double f)
{
    return sqrt((a-d)*(a-d)+(b-e)*(b-e)+(c-f)*(c-f));
}
void play()
{
    double MAX=0;
    for(int i=0; i<n; i++)
    {
        for(int j=i+1; j<n; j++)
        {
            dist[i*2][j*2]=cal(JLJ[i*2].a,JLJ[i*2].b,JLJ[i*2].c,JLJ[j*2].a,JLJ[j*2].b,JLJ[j*2].c);
            dist[i*2][j*2+1]=cal(JLJ[i*2].a,JLJ[i*2].b,JLJ[i*2].c,JLJ[j*2+1].a,JLJ[j*2+1].b,JLJ[j*2+1].c);
            dist[i*2+1][j*2]=cal(JLJ[i*2+1].a,JLJ[i*2+1].b,JLJ[i*2+1].c,JLJ[j*2].a,JLJ[j*2].b,JLJ[j*2].c);
            dist[i*2+1][j*2+1]=cal(JLJ[i*2+1].a,JLJ[i*2+1].b,JLJ[i*2+1].c,JLJ[j*2+1].a,JLJ[j*2+1].b,JLJ[j*2+1].c);
            MAX=max(MAX,dist[i*2][j*2]);
            MAX=max(MAX,dist[i*2][j*2+1]);
            MAX=max(MAX,dist[i*2+1][j*2]);
            MAX=max(MAX,dist[i*2+1][j*2+1]);
        }
    }
    double l=0;
    double r=MAX;
    double over=0;
    while(l<=r)
    {
        double mid=(l+r)/2;
        double d=mid*2;
        bool flag=1;
        for(int i=0; i<=2*n; i++)V[i].clear();
        for(int i=0; i<n; i++)
        {  if(!flag)break;
            for(int j=i+1; j<n; j++)
            {
                if(dist[i*2][j*2]<d&&dist[i*2+1][j*2]<d&&dist[i*2][j*2+1]<d&&dist[i*2+1][j*2+1]<d)
                {
                    flag=0;
                    break;
                }
                if(dist[i*2][j*2+1]<d)
                {
                    V[i*2].push_back(j*2);
                    V[j*2+1].push_back(i*2+1);
                }
                if(dist[i*2][j*2]<d)
                {
                        V[i*2].push_back(j*2+1);
                        V[j*2].push_back(i*2+1);
                }
                if(dist[i*2+1][j*2+1]<d)
                {
                    V[i*2+1].push_back(j*2);
                    V[j*2+1].push_back(i*2);
                }
                if(dist[i*2+1][j*2]<d)
                {
                    V[i*2+1].push_back(j*2+1);
                    V[j*2].push_back(i*2);
                }

            }
        }
        if(!flag){
            r=mid-e;
            continue;
        }
        indexx=cntnum=0;
        scnt=-1;
        memset(dfn,-1,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        for(int i=0; i<2*n; i++)
        {
            if(dfn[i]==-1)tarjan(i);
        }
        for(int i=0; i<n; i++)
        {
            if(belong[i*2]==belong[i*2+1])
            {
                flag=0;
                break;
            }
        }
        if(!flag)
        {
            r=mid-e;
            continue;
        }
        over=max(over,l);
        l=mid+e;

    }
    printf("%.4lf\n",over);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init();
        play();
    }
    //  cout << "Hello world!" << endl;
    return 0;
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter