题目链接https://vjudge.net/contest/306976#problem
题目大意:需要在n个星球上各装一个广播装置,作用范围均为R。每个星球广播A类节目或者B类节目。a表示星球i收听到的和自己广播相同节目的星球数(包括星球i自己),b表示不想同,如果a<b,说明星球是不稳定的,现在要选择尽量小的R,使得不稳定的星球尽量多些。
输入格式:x,y,z,p(三维坐标和收听的节目0或1)
输出格式:不稳定的星球数和R(注意Sample Output中第一行的14应该为4)
emmm,有点头痛的题目,其实只要想清楚R一定在dis(任意两个星球的距离)中就抓住了思路了。
我们先算出任意两个星球的距离,然后将其排序(从小到大),能够注意到的是大R的信息一定包含了小R的信息,所以计算稳定与不稳定数量的时候可以用之前小R的递推而来:
numb[i]=1;
****
int r=0,num=0,cnt=0;
sort(dis+1,dis+1+k);
for (int i=1; i<=k; i++) {
int xx=dis[i].be,yy=dis[i].fin;//第i个距离所连接的两个星球
if (sta[xx].id!=sta[yy].id) {
numb[xx]--;//直接利用之前小R所保存的信息
numb[yy]--;
if (numb[xx]==-1) cnt++;//减到-1就说明a<b了
if (numb[yy]==-1) cnt++;
} else {
numb[xx]++;
numb[yy]++;
if (numb[xx]==0) cnt--;//从负数加了回来,说明扩大后平衡了,所以要恢复
if (numb[yy]==0) cnt--;
}
if (i!=k && dis[i].len==dis[i+1].len) continue;//处理等距离的情况
if (num<cnt) {
num=cnt;
r=dis[i].len;
}
}
以上的就是核心代码了,如果懂了的话这题就结束了。
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int id,x,y,z;
}sta[1005];
struct node1
{
int be,fin,len;
bool operator < (const node1& a) const{
return len<a.len;
}
}dis[1005*1005];
int numb[1005];
int getdis(int a,int b);
int pw(int x);
int main()
{
int n;
while (scanf ("%d",&n)!=EOF){
int k=0,x,y,z,p;
for (int i=1; i<=n; i++){
scanf ("%d%d%d%d",&x,&y,&z,&p);
sta[i]=(node){p,x,y,z};
numb[i]=1;
}
for (int i=1; i<=n; i++)
for (int j=i+1; j<=n; j++){
dis[++k].be=i;dis[k].fin=j;
dis[k].len=getdis(i,j);
}
int r=0,num=0,cnt=0;
sort(dis+1,dis+1+k);
for (int i=1; i<=k; i++){
int xx=dis[i].be,yy=dis[i].fin;
if (sta[xx].id!=sta[yy].id){
numb[xx]--;
numb[yy]--;
if (numb[xx]==-1) cnt++;
if (numb[yy]==-1) cnt++;
}
else {
numb[xx]++;
numb[yy]++;
if (numb[xx]==0) cnt--;
if (numb[yy]==0) cnt--;
}
if (i!=k && dis[i].len==dis[i+1].len) continue;
if (num<cnt){
num=cnt;
r=dis[i].len;
}
}
printf ("%d\n%.4f\n",num,sqrt(r*1.0));
}
return 0;
}
int pw(int x)
{
return x*x;
}
int getdis(int a,int b)
{
int sum=pw(sta[a].x-sta[b].x)+pw(sta[a].y-sta[b].y)+pw(sta[a].z-sta[b].z);
return sum;
}