笔试-射击游戏

题目

https://www.nowcoder.com/questionTerminal/d3f26db0325444078717cc802e0056d8

题意

小易正在玩一款新出的射击游戏,这个射击游戏在一个二维平面进行,小易在坐标原点(0,0),平面上有n只怪物,每个怪物有所在的坐标(x[i], y[i])。小易进行一次射击会把x轴和y轴上(包含坐标原点)的怪物一次性消灭。
小易是这个游戏的VIP玩家,他拥有两项特权操作:
1、让平面内的所有怪物同时向任意同一方向移动任意同一距离
2、让平面内的所有怪物同时对于小易(0,0)旋转任意同一角度
小易要进行一次射击。小易在进行射击前,可以使用这两项特权操作任意次。
小易想知道在他射击的时候最多可以同时消灭多少只怪物,请你帮帮小易。

如样例所示:

所有点对于坐标原点(0,0)顺时针或者逆时针旋转45°,可以让所有点都在坐标轴上,所以5个怪物都可以消灭。

输入描述:

输入包括三行。
第一行中有一个正整数n(1 ≤ n ≤ 50),表示平面内的怪物数量。
第二行包括n个整数x[i](-1,000,000 ≤ x[i] ≤ 1,000,000),表示每只怪物所在坐标的横坐标,以空格分割。
第二行包括n个整数y[i](-1,000,000 ≤ y[i] ≤ 1,000,000),表示每只怪物所在坐标的纵坐标,以空格分割。

输出描述:

输出一个整数表示小易最多能消灭多少只怪物。

输入例子1:

5
0 -1 1 1 -1
0 -1 -1 1 1

输出例子1:

5

题解

题目其实就是求两条垂直的直线上最多可以有多少个点。
两个for,两个点AB确定一条直线,第三个for,第三个点C通过另一条直线,第四个for,对于剩下 的n-3个点,如果在AB确定的直线上或者与C点构成的直线与AB垂直均可以。第四个for结束后,更新一次最大值。
最后输出最大值即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <bits/stdc++.h>
using namespace std;
double eps=1e-9;
int sgn(double x)
{
if(x<-eps) return -1;
if(x>eps) return 1;
return 0;
}
double cross(int x1,int y1,int x2,int y2)
{
return x1*y2-x2*y1;
}

double dot(int x1,int y1,int x2,int y2)
{
return x1*x2+y1*y2;
}

bool point_on_segment(int x1,int y1,int x2,int y2,int px,int py)
{
return sgn(cross(x1-px,y1-py,x2-px,y2-py))==0;
}

bool isVertical(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
return sgn(dot(x1-x2,y1-y2,x3-x4,y3-y4))==0;
}

int main()
{
int n;
cin>>n;
vector<int> x(n),y(n);
for(int i=0; i<n; i++)
cin>>x[i];
for(int i=0; i<n; i++)
cin>>y[i];
int mmax = 0;
if(n<4) mmax = n;
for(int i=0; i<n; i++)
{
for(int j=i+1; j<n; j++)
{
for(int p=0; p<n; p++)
{
if(p==i||p==j) continue;
int ans = 3;
for(int q=0; q<n; q++)
{
if(q==i||q==j||q==p) continue;
if(point_on_segment(x[i],y[i],x[j],y[j],x[q],y[q])||
isVertical(x[i],y[i],x[j],y[j],x[p],y[p],x[q],y[q]))
ans++;
}
mmax= max(mmax,ans);
}
}
}
cout<<mmax<<endl;
return 0;
}