cf850A

http://www.elijahqi.win/archives/678
A. Five Dimensional Points
time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

You are given set of n points in 5-dimensional space. The points are labeled from 1 to n. No two points coincide.

We will call point a bad if there are different points b and c, not equal to a, from the given set such that angle between vectors and is acute (i.e. strictly less than ). Otherwise, the point is called good.

The angle between vectors and in 5-dimensional space is defined as , where is the scalar product and is length of .

Given the list of points, print the indices of the good points in ascending order.

Input
The first line of input contains a single integer n (1 ≤ n ≤ 103) — the number of points.

The next n lines of input contain five integers ai, bi, ci, di, ei (|ai|, |bi|, |ci|, |di|, |ei| ≤ 103) — the coordinates of the i-th point. All points are distinct.

Output
First, print a single integer k — the number of good points.

Then, print k integers, each on their own line — the indices of the good points in ascending order.

Examples
input
6
0 0 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
output
1
1
input
3
0 0 1 2 0
0 0 9 2 0
0 0 5 9 0
output
0
Note
In the first sample, the first point forms exactly a angle with all other pairs of points, so it is good.

In the second sample, along the cd plane, we can see the points look as follows:

We can see that all angles here are acute, so no points are good.

我们可以知道如果90°的时候应该是最大满足条件,举个例子,二维,在四个坐标系上,正好四个

推广到k维,最多有2*k个。就本题而言,最多10个点能满足题意。也就是说n如果>=12,是一定不满足题意的,直接输出0即可。剩下的情况n很小,可以直接暴力O(n3)判断。

在评论中看到的一个想法,跟大家分享一下:算出两两点之间的连线的长度,找到最小的那条线段,记作ab,则好点一定出自a,b。其他点一定都是坏点。为什么呢?首先,如果另一点c和a,b构成了三角形abc,则小边对小角,角C一定是不大于60°的,也就是说c一定是坏点。另一种情况,a,b,c三点一线,因为ab是最短的,所以c一定在a,b同侧,所以c还是个坏点。综上,除了a,b以外的点都是坏点。我们只需判断a,b是否是好点即可。

#include<cstdio>
#include<cmath>
inline int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int top,q[15],p[15][6];
inline double calc(int x,int y,int z){
    int x1[6],x2[6];
    for (int i=1;i<=5;++i) x1[i]=p[y][i]-p[x][i];
    for (int i=1;i<=5;++i) x2[i]=p[z][i]-p[x][i];
    double len1=0,len2=0;
    for (int i=1;i<=5;++i) len1+=x1[i]*x1[i];len1=sqrt(len1);
    for (int i=1;i<=5;++i) len2+=x2[i]*x2[i];len1=sqrt(len2);
    int ans=0;
    for (int i=1;i<=5;++i) ans+=x1[i]*x2[i];
    return ans/(len1*len2);
}
int n;
int main(){
    freopen("cfc.in","r",stdin);
    n=read();
    if (n>11){printf("0");return 0;}
    for (int i=1;i<=n;++i) 
        for (int j=1;j<=5;++j) p[i][j]=read();
    bool flag;
    for (int i=1;i<=n;++i){
        flag=true;
        for (int j=1;j<=n;++j){
            if (i==j) continue;
            for (int z=1;z<=n;++z){
                if (j==z) continue;if (i==z) continue;
                if (calc(i,j,z)>0) {
                    flag=false;break;
                }
            }
            if (flag==false) break;
        }
        if (flag) q[++top]=i;
    }
    printf("%d\n",top);
    for (int i=1;i<=top;++i) printf("%d\n",q[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值