第五届新疆省ACM-ICPC程序设计竞赛 A Good 的集合

链接:https://ac.nowcoder.com/acm/contest/911/A
来源:牛客网

题目描述

平面上给 n(3≤n≤1000) 个点,保证不存在 3 点共线,保证这些点两两不重合,对于一个点集 S ,如果从 S 中任意选出三个不同的点,构成的三角形重心都不是整点(横坐标,纵坐标都是整数的点,称为整点),那么这个点集是  good 的,输出最大的 good 的点集大小。(注:所有点数小于等于 2 的点集都是 good 的)。

输入描述:

第一行,一个整数 n(3≤n≤1000),表示 n 个点,之后 n 行,每行两个整数 x[i],y[i](0≤x[i],y[i]≤10^6).

输出描述:

输出一个正整数表示答案。

示例1

输入

4
0 0
0 1
1 0
1 1

输出

4

示例2

输入

3
0 0
1 2
2 1

输出

2

备注:

* 样例 1 所有点都可以加入集合。

* 样例 2,如果 3 个点同时加入集合,重心为 (1,1) 不合法,Good Set 中至多只能 2 个点。

题解:

重心公式 x=(x1+x2+x3)/3,   y=(y1+y2+y3)/3;

那么首先我们可以将每个点的横纵坐标都模3.那么实际上终于9类型的点,(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2).

并统计一下每类型点的个数。

显然,每类型的点最多只能选两个,因为如果选了3个,那么这三个点构成的三角形重心就是整数坐标了,这9类型的点我们可以用二进制去枚举选哪几个,然后check是否合法,取合法里的最大值即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
pair<int,int> p[10];
int cnt[10];
int n,m;
int a[3][3];
vector<pair<int,int> > v;
bool judge(int i,int j,int k){
    if((v[i].first+v[j].first+v[k].first)%3==0&&(v[i].second+v[j].second+v[k].second)%3==0) return true;
    return false;
}
bool check(){
    for(int i=0;i<v.size();i++){
        for(int j=i+1;j<v.size();j++){
            for(int k=j+1;k<v.size();k++){
                if(judge(i,j,k)) return false;
            }
        }
    }
    return true;
}
int main(){
    cin>>n;
    while(n--){
        int x,y;
        scanf("%d%d",&x,&y);
        a[x%3][y%3]++;
    }
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            if(a[i][j]==0) continue;
            int x=min(2,a[i][j]);
            p[m].first=i;p[m].second=j;
            cnt[m]=x;
            m++;
        }
    }
    int ans=0;
    for(int i=1;i<(1<<m);i++){
        v.clear();
        int t=0;
        for(int j=0;j<m;j++){
            if(i>>j&1) v.push_back(p[j]),t+=cnt[j];
        }
        if(check()) ans=max(ans,t);
    }
    cout<<ans<<endl;
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值