题目链接:UVA1325
【题意】要在n个星球上各装一个广播装置,作用范围均为R(即和它距离不超过R的星球能收听到它的广播)。每个星球广播A类节目或者B类节目。另N+(i)表示星球i能收听到的和自己广播相同节目的星球数量(包括星球i自己),N-(i)表示星球i收听到广播另一种节目的星球数。如果N+(i)<N-(i),我们就说星球i是不稳定的。你是暗黑世界的间谍,因此希望选择R,使得不稳定的星球尽量多。在此前提下,R应尽量小。
【分析】需要用扫描的思想,直接暴力肯定超时的,首先可以知道最大不稳定的星球数量肯定在r的值为某两个星球的距离,这样先枚举出所有星球之间的距离,这样已经是O(N^2)复杂度了,对于1000的N来说基本上只能线性扫描了;还可以发现只要把距离从小到大排序,以前小的距离计算过的每个星球的稳定值na(就是[n+(i)] – [n-(i)]的值)可以被大的距离所利用,每次改变的na其实只是距离为当前r的所有两两对应的星球,这样只要两个星球为同一频段那就把两个星球的na都+1,反之-1,这样每次当-++na == 0时说明这个星球刚好从不稳定变成稳定,–na==-1时改星球从稳定变成不稳定;最后需要注意把所有距离相等的要都算完后再更新ans,还有所有星球都是同一频段的时候r为0、
【AC CODE】343ms
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
//#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 1000 + 10;
struct NODE{
int x, y, z, type;
}p[MAXN];
struct S{
int u, v, dis;
bool operator<(const S&t)const{
return dis < t.dis;
}
}s[MAXN*MAXN];
int na[MAXN];//na+和na-的差,na<0时表示星球不稳定
inline int get_dis(int a, int b)
{
return (p[a].x - p[b].x)*(p[a].x - p[b].x) + (p[a].y - p[b].y)*(p[a].y - p[b].y) + (p[a].z - p[b].z)*(p[a].z - p[b].z);
}
int main()
{
#ifdef SHY
freopen("d:\\1.txt", "r", stdin);
#endif
int n;
while (~scanf("%d%*c", &n))
{
rep(i, 0, n) scanf("%d %d %d %d%*c", &p[i].x, &p[i].y, &p[i].z, &p[i].type);
int cnt = 0;
rep(i, 0, n)
{
na[i] = 1;
rep(j, i + 1, n)
s[cnt++] = { i, j, get_dis(i, j) };
}
sort(s, s + cnt);
int ans = 0, tmp = 0, r = 0;
rep(i, 0, cnt)
{
int u = s[i].u, v = s[i].v;
if (p[u].type == p[v].type)
{
if (++na[u] == 0) tmp--;
if (++na[v] == 0) tmp--;
}
else
{
if (--na[u] == -1) tmp++;
if (--na[v] == -1) tmp++;
}
if (i != cnt - 1 && s[i].dis == s[i + 1].dis) continue;
if (tmp > ans)
{
ans = tmp;
r = s[i].dis;
}
}
printf("%d\n%.4f\n", ans, sqrt((double)r));
}
return 0;
}