BoxerTC

Zombie Blast

Oct 26th, 2014
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.60 KB | None | 0 0
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define sc( x ) scanf( "%d" , &x )
  5. #define REP( i , n ) for( int i = 0 ; i < n ; ++i )
  6. #define clr( t , val ) memset( t , val , sizeof( t ) )
  7.  
  8. #define pb push_back
  9.  
  10. #define N 2000
  11.  
  12. typedef long long ll;
  13. typedef long long ntype;
  14. const ntype sentry = numeric_limits<ntype>::max();
  15.  
  16. struct point {
  17.     ntype x, y;
  18.     point(ntype xx = 0, ntype yy = 0) : x(xx), y(yy) {}
  19. };
  20. bool operator==(const point &a, const point &b){
  21.     return a.x == b.x && a.y == b.y;
  22. }
  23. bool on_x(const point &a, const point &b){
  24.     return a.x < b.x;
  25. }
  26. bool on_y(const point &a, const point &b){
  27.     return a.y < b.y;
  28. }
  29. ntype pdist2(const point &a, const point &b){
  30.     ntype dx = a.x-b.x, dy = a.y-b.y;
  31.     return dx*dx + dy*dy;
  32. }
  33. struct bbox{
  34.     ntype x0, x1, y0, y1;
  35.     bbox() : x0(sentry), x1(-sentry), y0(sentry), y1(-sentry) {}
  36.     void compute(const vector<point> &v) {
  37.         for (int i = 0; i < v.size(); ++i) {
  38.             x0 = min(x0, v[i].x);   x1 = max(x1, v[i].x);
  39.             y0 = min(y0, v[i].y);   y1 = max(y1, v[i].y);
  40.         }
  41.     }
  42.     ntype distance(const point &p) {
  43.         if (p.x < x0) {
  44.             if (p.y < y0)       return pdist2(point(x0, y0), p);
  45.             else if (p.y > y1)  return pdist2(point(x0, y1), p);
  46.             else                return pdist2(point(x0, p.y), p);
  47.         }
  48.         else if (p.x > x1) {
  49.             if (p.y < y0)       return pdist2(point(x1, y0), p);
  50.             else if (p.y > y1)  return pdist2(point(x1, y1), p);
  51.             else                return pdist2(point(x1, p.y), p);
  52.         }
  53.         else {
  54.             if (p.y < y0)       return pdist2(point(p.x, y0), p);
  55.             else if (p.y > y1)  return pdist2(point(p.x, y1), p);
  56.             else                return 0;
  57.         }
  58.     }
  59. };
  60. struct kdnode {
  61.     bool leaf;
  62.     point pt;
  63.     bbox bound;
  64.    
  65.     kdnode *first, *second;
  66.    
  67.     kdnode() : leaf(false), first(0), second(0) {}
  68.     ~kdnode() { if (first) delete first; if (second) delete second; }
  69.    
  70.     ntype intersect(const point &p) {
  71.         return bound.distance(p);
  72.     }
  73.    
  74.     void construct(vector<point> &vp)
  75.     {
  76.         bound.compute(vp);
  77.         if (vp.size() == 1) {
  78.             leaf = true;
  79.             pt = vp[0];
  80.         }
  81.         else {
  82.             if (bound.x1-bound.x0 >= bound.y1-bound.y0)
  83.                 sort(vp.begin(), vp.end(), on_x);
  84.             else
  85.                 sort(vp.begin(), vp.end(), on_y);
  86.             int half = vp.size()/2;
  87.             vector<point> vl(vp.begin(), vp.begin()+half);
  88.             vector<point> vr(vp.begin()+half, vp.end());
  89.             first = new kdnode();   first->construct(vl);
  90.             second = new kdnode();  second->construct(vr);            
  91.         }
  92.     }
  93. };
  94. struct kdtree{
  95.     kdnode *root;
  96.     kdtree(const vector<point> &vp) {
  97.         vector<point> v(vp.begin(), vp.end());
  98.         root = new kdnode();
  99.         root->construct(v);
  100.     }
  101.     ~kdtree() { delete root; }
  102.     ntype search(kdnode *node, const point &p){
  103.         if (node->leaf) {
  104.                 return pdist2(p, node->pt);
  105.         }
  106.        
  107.         ntype bfirst = node->first->intersect(p);
  108.         ntype bsecond = node->second->intersect(p);
  109.        
  110.         if (bfirst < bsecond) {
  111.             ntype best = search(node->first, p);
  112.             if (bsecond < best)
  113.                 best = min(best, search(node->second, p));
  114.             return best;
  115.         }
  116.         else {
  117.             ntype best = search(node->second, p);
  118.             if (bfirst < best)
  119.                 best = min(best, search(node->first, p));
  120.             return best;
  121.         }
  122.     }
  123.     ntype nearest(const point &p) {
  124.         return search(root, p);
  125.     }
  126. };
  127. char S[ N + 5 ][ N + 5 ];
  128. int main(){
  129.    
  130.     int cases , n , m;
  131.     sc( cases );
  132.     REP( tc , cases ){
  133.         sc( m ) , sc( n );
  134.         REP( i , n ) scanf( "%s" , S[ i ] );
  135.         vector<point> vp;
  136.         REP( i , n )REP( j , m )
  137.             if( S[ i ][ j ] == 'M' ){
  138.                 vp.pb( point( i , j ) );
  139.             }
  140.         kdtree tree(vp);
  141.         ll ans = 0;
  142.         REP( i , n )REP( j , m )if( S[ i ][ j ] == 'Z' ){
  143.             ans = max( ans , tree.nearest( point( i , j ) ) );
  144.         }
  145.         printf( "%.10f\n" , (double)sqrt( ans ) );
  146.     }
  147.    
  148.     /*
  149.     vector<point> vp;
  150.     for (int i = 0; i < 4000000; ++i) {
  151.         vp.push_back(point(rand()%100000, rand()%100000));
  152.     }
  153.     kdtree tree(vp);
  154.    
  155.     // query some points
  156.     for (int i = 0; i < 4000000; ++i) {
  157.         point q(rand()%100000, rand()%100000);
  158.         cout << "Closest squared distance to (" << q.x << ", " << q.y << ")"
  159.              << " is " << tree.nearest(q) << endl;
  160.     }    
  161.     */
  162. }
Advertisement
Add Comment
Please, Sign In to add comment