Connect the countless points with lines, till we reach the faraway yonder.
There are n points on a coordinate plane, the i-th of which being (i, yi).
Determine whether it’s possible to draw two parallel and non-overlapping lines, such that every point in the set lies on exactly one of them, and each of them passes through at least one point in the set.
Input
The first line of input contains a positive integer n (3 ≤ n ≤ 1 000) — the number of points.
The second line contains n space-separated integers y1, y2, …, yn ( - 10^9 ≤ yi ≤ 10^9) — the vertical coordinates of each point.
Output
Output “Yes” (without quotes) if it’s possible to fulfill the requirements, and “No” otherwise.
You can print each letter in any case (upper or lower).
Examples
input
5
7 5 8 6 9
output
Yes
input
5
-1 -2 0 0 -5
output
No
input
5
5 4 3 2 1
output
No
input
5
1000000000 0 0 0 0
output
Yes
Note
In the first example, there are five points: (1, 7), (2, 5), (3, 8), (4, 6) and (5, 9). It’s possible to draw a line that passes through points 1, 3, 5, and another one that passes through points 2, 4 and is parallel to the first one.
In the second example, while it’s possible to draw two lines that cover all points, they cannot be made parallel.
In the third example, it’s impossible to satisfy both requirements at the same time.
大致题意:在二维平面上有n个点,告诉你这n个点的坐标,然后问你是否能找出两条不重合的平行线,使得所有的点,一部分在其中一条线上,另外一部分在另一条线上。
思路:注意到所有的点x坐标都不同,所以过两点的直线的斜率一定存在。假设存在满足条件的两条平行线a,b,那么所有的点不是在直线a上就是在直线b上,所以我们可以先求出1号点与其他所有点的斜率,然后从中选择一个斜率k作为当前一条平行线的斜率。接下来遍历所有的点,如果某个点与1号点的斜率不为k,说明这个点应该在另一条平行线上,记录一下,然后判断这些点是否能组成另一条平行线且斜率为k。具体实现看代码。
注意:如果所有的点都在同一条直线上是不行的。
代码如下
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int a[1005];//记录每个点的纵坐标,横坐标即编号
double ans[1005];//记录编号2~n的点与编号1连线的斜率
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i!=1)
{
ans[i]=(a[i]-a[1])*1.0/(i-1);
}
}
int flag1=0;
for(int i=2;i<=n;i++)
{
double k1=ans[i];//选择一个斜率
int f=0;//记录斜率不同的点的个数
int x;
int flag2=1;
for(int j=2;j<=n;j++)//遍历其它点
{
if(j==i)
continue;
if(ans[j]!=k1)//如果点j与点1的连线斜率不为k1,说明应该在另一条平行线上
{
if(f==0)//如果是第一个斜率不同的点
{
x=j;
f++;
}
else//否则此时的点j与第一个斜率不同的点的连线的斜率应该为k1
{
f++;
if((a[j]-a[x])*1.0/(j-x)!=k1)//如果不是k1,说明此时选择的点i和点1构成的平行线是错的,结束循环,寻找其它可能情况
{
flag2=0;
break;
}
}
}
}
if(f==0)//如果所有的点都在用一条直线上
{
printf("No\n");
return 0;
}
if(flag2)//如果此时的情况满足条件,结束循环
{
flag1=1;
break;
}
}
if(flag1)
printf("Yes\n");
else //此时还有一种情况就是点1单独,其余的点都在都一条直线上
{
double k=(a[3]-a[2])*1.0;
for(int i=4;i<=n;i++)
{
if((a[i]-a[2])*1.0/(i-2)!=k)
{
printf("No\n");
return 0;
}
}
printf("Yes\n");
}
}