ZOJ 3717 Balloon ( TLE )

正解2-SAT。

我用DLX想搜一搜的,结果TLE了……

没什么遗憾,最起码我尝试过了。

扔个代码留作纪念。

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>



using namespace std;



const int INF = 1 << 30;

const int MAXN = 450;

const double eps = 1e-9;



struct Point

{

    double x, y, z;

    Point( double x = 0, double y = 0, double z = 0 ):x(x), y(y), z(z){ }

    void readPoint()

    {

        scanf( "%lf%lf%lf", &x, &y, &z );

        return;

    }

};



bool mx[MAXN][800];    //01矩阵

int C[MAXN*800], cnt[800];

int U[MAXN*800], D[MAXN*800];

int L[MAXN*800], R[MAXN*800];

int head;

int maxr, maxc;

Point P[MAXN];

int N;



int dcmp( double a )

{

    if ( fabs(a) < eps ) return 0;

    return a < 0 ? -1 : 1;

}



double Dis( Point a, Point b )

{

    return sqrt( ( a.x - b.x )*( a.x - b.x ) + ( a.y - b.y )*( a.y - b.y ) + ( a.z - b.z )*( a.z - b.z ) );

}



void Remove( int c )

{

    int i, j;

    L[ R[c] ] = L[c];

    R[ L[c] ] = R[c];

    for ( i = D[c]; i != c; i = D[i] )

    {

        for ( j = R[i]; j != i; j = R[j] )

        {

            U[ D[j] ] = U[j];

            D[ U[j] ] = D[j];

            --cnt[ C[j] ];

        }

    }

    return;

}



void Resume( int c )

{

    int i, j;

    R[ L[c] ] = c;

    L[ R[c] ] = c;

    for ( i = D[c]; i != c; i = D[i] )

    {

        for ( j = R[i]; j != i; j = R[j] )

        {

            U[ D[j] ] = j;

            D[ U[j] ] = j;

            ++cnt[ C[j] ];

        }

    }

    return;

}



bool DFS( int cur )

{

    int i, j, c, minv;



    if ( cur > N ) return false;

    if ( R[head] == head )

    {

        if ( cur == N )

            return true;

        return false;

    }



    minv = INF;

    for ( i = R[head]; i != head; i = R[i] )

    {

        if ( cnt[i] < minv )

        {

            minv = cnt[i];

            c = i;

        }

    }



    Remove(c);

    for ( i = D[c]; i != c; i = D[i] )

    {

        for( j = R[i]; j != i; j = R[j] )

            Remove( C[j] );



        if ( DFS( cur + 1 ) ) return true;



        for( j = R[i]; j != i; j = R[j] )

            Resume( C[j] );

    }



    Resume(c);

    return false;

}



bool build()

{

    int i, j, cur, pre, first;

    head = 0;

    for ( i = 0; i < maxc; ++i )

    {

        R[i] = i + 1;

        L[i + 1] = i;

    }

    R[ maxc ] = 0;

    L[0] = maxc;



    //列双向链表

    for ( j = 1; j <= maxc; ++j )

    {

        pre = j;

        cnt[j] = 0;

        for ( i = 1; i <= maxr; ++i )

        {

            if ( mx[i][j] )

            {

                ++cnt[j];

                cur = i * maxc + j;  //当前节点的编号

                C[cur] = j;          //当前节点所在列

                D[pre] = cur;

                U[cur] = pre;

                pre = cur;

            }

        }

        U[j] = pre;

        D[pre] = j;

        if ( !cnt[j] ) return false; //一定无解

    }



    //行双向链表

    for ( i = 1; i <= maxr; ++i )

    {

        pre = first = -1;

        for ( j = 1; j <= maxc; ++j )

        {

            if( mx[i][j] )

            {

                cur = i * maxc + j;

                if ( pre == -1 ) first = cur;

                else

                {

                    R[pre] = cur;

                    L[cur] = pre;

                }

                pre = cur;

            }

        }

        if ( first != -1 )

        {

            R[pre] = first;

            L[first] = pre;

        }

    }

    return true;

}



/**************以上DLX模板*****************/



void show()

{

    for ( int i = 0; i <= maxr; ++i )

    {

        for ( int j = 0; j <= maxc; ++j )

            printf( "%d", mx[i][j] );

        puts("");

    }

    puts("---------");

    return;

}



//得到该情况下的01矩阵

void init( double R )

{

    memset( mx, false, sizeof(mx) );



    for ( int i = 1; i <= maxr; ++i )

    {

        mx[i][i] = true;

        if ( i % 2 )

        {

            //printf("ii %d %d\n", i, i + 1);

            mx[i][N + N + i/2+1] = true;

            mx[i + 1][N + N + i/2+1] = true;

        }

        for ( int j = 1; j <= maxr; ++j )

        {

            //printf("i=%d j=%d\n", i, j );

            if ( dcmp( Dis( P[i], P[j] ) - 2.0 * R ) < 0 )

                mx[j][i] = true;

        }

    }

    //show();

    return;

}



bool ok( double mid )

{

    init( mid );

    if ( build() == false ) return false;

    if ( DFS( 0 ) == false ) return false;

    return true;

}



double solved()

{

    double l = 0;

    double r = Dis( Point(0, 0, 0), Point( 10000, 10000, 10000 ) );

    double ans;

    while ( dcmp( r - l ) > 0 )

    {

        double mid = ( l + r ) / 2.0;

        //printf( "mid = %.6f\n", mid );

        if ( ok( mid ) )

        {

            l = mid;

            ans = mid;

        }

        else r = mid;

    }

    return ans;

}



int main()

{

    //freopen( "in.txt", "r", stdin );

    //freopen( "out.txt", "w", stdout );

    while ( scanf( "%d", &N ) == 1 )

    {

        maxr = 0;

        for ( int i = 0; i < N; ++i )

        {

            P[++maxr].readPoint();

            P[++maxr].readPoint();

        }

        maxc = maxr + N;

        double ans=(int)(solved()*1000+0.5+eps)/1000.0;

        if ( !ok(ans) ) ans -= 0.001;

        printf( "%.3f\n", ans );

    }

    return 0;

}

 

你可能感兴趣的:(ZOJ)