DFS --- HNU 13307 Galaxy collision

本文探讨了在二维坐标平面上给定一组整数点时,如何将其划分为两个集合,使得同一集合内的任意两点间距离大于5,通过遍历可能的‘虚点’和深度优先搜索(DFS)来确定两个集合的最大元素数量差。

Galaxy collision 

Problem's Link


 

Mean: 

给定二维坐标平面内的n个整数点,让你把这n个点划分为两个集合,同一集合内的所有点必须两两距离大于5,求这两个集合的元素个数之差最大是多少。

analyse:

由题意可知:同一个圆内包含的点肯定不能和这个圆心点在同一集合,且题目保证了一定有答案。

而且都是整数点,每个圆包含的点不会超过100个,那么就可以枚举园内的每一个"虚点"看题目中有没有出现这个点,然后对所有点DFS,ans1统计点多的集合,ans2统计点少的集合,最后相减即得答案。

Time complexity: O(N)

 

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-10-06-23.02
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define max(a,b) (a>b?a:b)
using namespace std;
typedef long long( LL);
typedef unsigned long long( ULL);
const double eps( 1e-8);

struct Point
{
      int x , y;
      Point() {}
      Point( int x , int y)
      {
            this -> x = x;
            this -> y = y;
      }
      bool operator <( Point one) const
      {
            if( x != one . x)
                  return x < one . x;
            return y < one . y;
      }
};
vector < Point > bx;
int dis2( Point one , Point two)
{
      return ( one . x - two . x) *( one . x - two . x) +( one . y - two . y) *( one . y - two . y);
}
void create()
{
      for( int i =- 5; i <= 5; i ++)
            for( int j =- 5; j <= 5; j ++)
                  if( dis2( Point( i , j ), Point( 0 , 0)) <= 25)
                        bx . push_back( Point( i , j));
}
map < Point , int > mp;
Point cnt;
int sum;
void dfs( Point v)
{
      sum ++;
      if( sum >= 100000)
            exit( 0);
      int n = bx . size (), no = mp [ v ];
      map < Point , int >:: iterator it;
      for( int i = 0; i <n; i ++)
      {
            Point t = Point( v . x + bx [ i ]. x , v . y + bx [ i ]. y);
            it = mp . find( t);
            if( it != mp . end() && it -> second == 0)
            {
                  if( no == 1)
                  {
                        it -> second = 2;
                        cnt . y ++;
                  }
                  else
                  {
                        it -> second = 1;
                        cnt . x ++;
                  }
                  dfs( t);
            }
      }
}
int main()
{
      int size = 256 << 20; // 256MB
      char *p = ( char *) malloc( size) + size;
      __asm__( "movl %0, %%esp \n " :: "r"(p));
      create();
      int n;
      scanf( "%d" , &n);
      while(n --)
      {
            Point t;
            scanf( "%d%d" , & t . x , & t . y);
            mp [ t ] = 0;
      }
      map < Point , int >:: iterator it;
      int ans = 0;
      for( it = mp . begin(); it != mp . end(); it ++)
      {
            if( it -> second == 0)
            {
                  it -> second = 1;
                  cnt . x = 1;
                  cnt . y = 0;
                  dfs( it -> first);
                  if( cnt . x > cnt . y)
                        swap( cnt . x , cnt . y);
                  ans += cnt . x;
            }
      }
      cout << ans << endl;
      return 0;
}

 

转载于:https://www.cnblogs.com/crazyacking/p/4677310.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值