UVALive 2963 Hypertransmission

题目链接:https://vjudge.net/problem/UVALive-2963

题目大意:有n个星球,每个星球坐标为(xi,yi,zi),可以看成一个点。每个星球广播A类节目或B类节目,广播范围为R(以该星球为中心半径为R的球体)。令N+(i)表示星球i听到的和自己广播相同节目的星球数(包括自己),N-(i)表示星球i听到的和自己广播不同节目的星球数。如果N+(i)<N-(i),则称星球i是不稳定的。求不稳定星球的最大数目以及在此前提下R的最小值。

思路:容易知道,R的值肯定为某两个星球之间的距离。因此将所有距离从小到大排序,并存储每个距离所对应的两个点。按顺序枚举每个距离,根据这些距离所对应的点更新N+(i)和N-(i)即可。又因为半径大的球会包含半径小的球,所以前面的结果可以适用于后面。


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <map>
#include <iostream>
#include <queue>
using namespace std;
typedef long long LL;
const int dr[] = {0,0,-1,1};
const int dc[] = {-1,1,0,0};
const int maxn = 1000 + 10;

struct Point
{
   int x, y, z, t;
}p[maxn];

struct Triple
{
	int d, pa, pb;
	bool operator < (const Triple& rhs) const {
		return d < rhs.d;
	}
	bool operator == (const Triple &rhs) const {
		return d == rhs.d;
	}
	Triple(int d = 0, int pa = 0, int pb = 0) : d(d),pa(pa),pb(pb){}
}tri[maxn*maxn];

int dist(const Point& A, const Point& B)
{
	return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) + (A.z-B.z)*(A.z-B.z);
}

int vis[maxn];

int main()
{
	int n;
	while(scanf("%d", &n) == 1)
	{
		for(int i = 0; i < n; i++) scanf("%d%d%d%d", &p[i].x, &p[i].y, &p[i].z, &p[i].t);
		int cnt = 0;
	    for(int i = 0; i < n; i++)
	       for(int j = i+1; j < n; j++)
	       	  tri[cnt++] = Triple(dist(p[i],p[j]), i, j);
	    sort(tri, tri+cnt);
        fill(vis, vis+n+2, 1);
        int temp = 0, ans = 0, R = 0, j;
        for(int i = 0; i < cnt;) {
           for(j = i; j < cnt && tri[j].d == tri[i].d; j++)
           {
           	  int ta = tri[j].pa, tb = tri[j].pb;
           	  if(p[ta].t != p[tb].t)
           	  {
           	  	 if(--vis[ta] == -1) temp++;
           	  	 if(--vis[tb] == -1) temp++;
           	  }
           	  else {
           	  	 if(++vis[ta] == 0) temp--;
           	  	 if(++vis[tb] == 0) temp--;
           	  }
           }
           if(temp > ans) {
           	  ans = temp;
           	  R = tri[i].d;
           }
           i = j;
        }
        printf("%d\n%.4f\n", ans, sqrt(R*1.0));
	}
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值