p2694_计算几何_枚举剪枝.cpp

来自「高手写的所有acm例程 在acm.zju.edu.cn 上的题目的例程」· C++ 代码 · 共 108 行

CPP
108
字号
#include <stdio.h>
#include <math.h>
#include <algorithm>

#define MAXN 40010
#define eps  1e-8
#define sqr(a) ((a)*(a))

using namespace std;

struct TPoint {
       double  x , y;
       double  distance ( TPoint & );
};

struct TCircle {
       TPoint  Mid;
       double  r;
       bool    visible;
       void    init () { scanf ( "%lf%lf%lf" , &r , &Mid.x , &Mid.y ); }
};

int            N , Rad [MAXN] , Pos [MAXN] , Sum;
TCircle        Circle [MAXN];

bool   init ();
void   solve ();
bool   cmp_rad ( const int & , const int & );
bool   cmp_pos ( const int & , const int & );
void   print ();

main ()
{
     while ( init () ) {
           solve ();
           print ();
     }
}

void print ()
{
     bool  first = true;
     printf ( "%d\n" , Sum );
     for ( int i = 0; i < N; i ++ ) if ( Circle [i].visible ) {
         if ( first ) first = false; else printf ( " " );
         printf ( "%d" , i + 1 );
     }
     printf ( "\n" );
}

bool cmp_pos ( const int & a , const int & b )
{
     return Circle [a].Mid.x < Circle [b].Mid.x;
}

bool cmp_rad ( const int & a , const int & b )
{
     return Circle [a].r > Circle [b].r;
}

void solve ()
{
     for ( int i = 0; i < N; i ++ ) Rad [i] = Pos [i] = i , Circle [i].visible = true;
     sort ( Rad , Rad + N , cmp_rad );
     sort ( Pos , Pos + N , cmp_pos );
     
     int low , high , mid , l1 , l2;
     double Key;
     
     for ( int i = Sum = 0; i < N; i ++ ) if ( Circle [Rad [i]].visible ) {
         Key = Circle [Rad [i]].Mid.x - Circle [Rad [i]].r;
         
         for ( low = -1 , high = N - 1; low + 1 < high; ) {
             mid = ( low + high ) >> 1;
             if ( Circle [Pos [mid]].Mid.x <= Key - eps ) low = mid;
             else high = mid;
         }
         l1 = high;
         
         Key = Circle [Rad [i]].Mid.x + Circle [Rad [i]].r;
         for ( low = 0 , high = N; low + 1 < high; ) {
             mid = ( low + high ) >> 1;
             if ( Circle [Pos [mid]].Mid.x <= Key + eps ) low = mid;
             else high = mid;
         }
         l2 = low;
         
         for ( int j = l1; j <= l2; j ++ )
             if ( Pos [j] != Rad [i] && Circle [Pos [j]].Mid.distance ( Circle [Rad [i]].Mid ) <= Circle [Rad [i]].r + eps )
                Circle [Pos [j]].visible = false;
         
         Sum ++;
     }
}

double TPoint :: distance ( TPoint & B )
{
       return sqrt ( sqr ( x - B.x ) + sqr ( y - B.y ));
}

bool   init ()
{
       scanf ( "%d" , &N ); if ( N == 0 ) return false;
       for ( int i = 0; i < N; i ++ )
           Circle [i].init ();
       return true;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?