这道题有思路,但是时间不够了,所以没来得及写出来,比赛结束之后我才按照思路写了一遍就AC了;当时没想出来…脑壳懵逼状态QAQ;
题意:给你n个点去找其他点使得找的其他点的数量最小,使得所有点都关于同一个中心有对应的点与之中心对称;
比如这种:
那么就不需要添加点了,因为他本来就可以关于p点对称了;
然后我和队友写了写,如果我去枚举每两个点之间的中心,然后记录出现的次数;那么不就可以直接取重叠最大的了吗?然后其他没有关于这个中心对称的点,不就是需要添加的点数吗?咦,好像是这个思路哈;
然后我就按照这种思路写了一下,首先可以发现这个问题:1.题目上说是点set,那么肯定不会有原始点重合;2.因为中点坐标是对应的配对的左边的x,y除以2,所以我肯定不能用double,来搞涩,所以我转换了一下:
这样去写不就避免了double了吗?
所以只需要去枚举两点之间的中心就可以了;
枚举是这样枚举滴:
定一个点去找其他配对点的中心;
比如这种:
因为第3个点和中心重了;那么我就只需要k(是重的点数)+Max(最大值为1,这里是配对数目,所以对应的点数应该为2Max);
所以剩下的一个点就是第1个点了,随便找一个就可以和他配对了;所以ans为1
具体思路:
1.利用map把点映射;然后记录重合中心最大值;
2.找第一个和1中记录的Max相等的map,然后说明这个点重了,所以用k标记一个1;
最后就是n-2Max-k;具体见代码注释;
原来map还不能把自定义类作为key值,长见识了,嘻嘻;
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
map<pair<int,int>,int> mm;
pair<int,int> p[1001];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d %d",&p[i].first,&p[i].second);
}
int Max=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){//枚举
pair<int,int> t;t.first=p[i].first+p[j].first;t.second=p[i].second+p[j].second;
mm[t]++;
Max=max(Max,mm[t]);//记录出现次数最多的中心点
}
}
int k=0;
for(int i=0;i<n;i++){//找和中心点重得最多的点是那个点
pair<int,int> tt;
tt.first=p[i].first*2;tt.second=p[i].second*2;
if(mm[tt]==Max){
k=1;break; //表示这个点是重的所以需要k=1
}
}
printf("%d\n",n-Max*2-k);//n个点-配对的数量*2-k重的一个
return 0;
}