题目描述
小H有一个巨大的棋盘,可以视为无限大的二维坐标系,上面有N个棋子,同一个位置不会有多个棋子。小H给出了如下的定义:
若存在点(x,y)(x,y∈R),满足对于所有的棋子,都存在一个棋子(可以是本身)和它关于(x,y)对称,则这个棋局是对称的,(x,y)称为对称中心。现在小H最多向棋盘上再下K个棋子,问有多少不同的(x,y),使得存在一种下法,让(x,y)成为对称中心,如果这样的(x,y)有无穷多个,则输出一行-1
小H有一个巨大的棋盘,可以视为无限大的二维坐标系,上面有N个棋子,同一个位置不会有多个棋子。小H给出了如下的定义:
若存在点(x,y)(x,y∈R),满足对于所有的棋子,都存在一个棋子(可以是本身)和它关于(x,y)对称,则这个棋局是对称的,(x,y)称为对称中心。现在小H最多向棋盘上再下K个棋子,问有多少不同的(x,y),使得存在一种下法,让(x,y)成为对称中心,如果这样的(x,y)有无穷多个,则输出一行-1
注:棋子只能下在格点处
输入描述:
一行,两个整数N,K
第2~N+1行,每行两个整数,表示一个棋子的位置
1≤N≤105,0≤K≤20,输入所有数的绝对值不超过109
输出描述:
一行,一个整数,意义见题目描述
输入
2 0
1 1
-1 -1
输出
1
题解:首先我们将这n个点排序,然后暴力最小和者最大的k个点所能构成的中心对称点即可,因为你最多只能添加k个点使得所有点中心对称,所以你往暴力中间若干点所构成的中心对称点没有意义,这样小的若干点和大的若干点一定不满足,然后我们对于每个暴力出的中心对称点O(n)去找还要添加几个点即可。为防止中心对称点重复,我们用set存一下即可。
#include<set>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100005
struct node
{
int x,y;
bool operator < (const node &b) const
{
if(x!=b.x)
return x<b.x;
return y<b.y;
}
bool operator == (const node &b) const
{
if(x==b.x && y==b.y)
return 1;
return 0;
}
node operator + (const node &b) const
{
node c;
c.x=x+b.x;c.y=y+b.y;
return c;
}
}a[maxn];
int n,k,ans;
set<node>s;
int work(node x)
{
if(s.count(x)) return 0;
s.insert(x);int i,j=n,cnt=0;
for(i=1;i<=j;i++)
{
while(i<j && x<a[i]+a[j]) j--,cnt++;
if(x==a[i]+a[j]) j--;
else cnt++;
}
return cnt<=k;
}
int main(void)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
if(k>=n)
{
printf("-1\n");
return 0;
}
sort(a+1,a+n+1);
for(int i=1;i<=k+1;i++)
for(int j=n-k;j<=n;j++)
ans+=work(a[i]+a[j]);
printf("%d\n",ans);
return 0;
}