http://codeforces.com/problemset/problem/849/B
题意:给你这样一个点,问你有没有这样两条互相平行的线,使得所有的点都在这样两条直线的其中一条上,如果有就Yes,没有就NO。
思路:xjb暴力,用点1和点I (i>1)枚举每一条直线,然后根据这条直线的斜率rat,把点分成两个部分,一部分是与点1的斜率rat相等的,另一部分是不相等,然后暴力另外一个不相等的部分,看他们的斜率是否等于rat。注意在判断的时候,如果只能分成一部分,那么说明所有点都在一条直线上,那么肯定是不满足,如果第二部分只有一个点,那么肯定是满足,当然第一个点是单独的集合也有可能,所以我一开始枚举点2和剩下的点的斜率,然后看1和2的斜率是否等于这些的斜率,如果不等,那么我就可以分成这样的两条直线,一条划过点1,剩余的一条划过2到n。而且注意到yi的范围是在-1e9到1e9之间,那么2e9,在计算器上算了一下,好像2e9超过了int范围吧,所以还要考虑溢出。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <stdlib.h>
#include <cmath>
#define maxn 1100
using namespace std;
typedef long long LL;
double rat[maxn];
int a[maxn];
int n;
bool flag;
map<double,bool> vis;
double tran(int x,int y)
{
double rate=(double)((LL)(a[x]-a[y]))/(double)(x-y);
//printf("%I64d\n",(LL)(a[x]-a[y]));
//printf("%d\n",x-y);
return rate;
}
bool check(double rat,int num)
{
vector<int> s[2];
//printf("IN:%d\n",num);
for(int i=2;i<=n;i++)
{
if(i==num)continue;
if(fabs(tran(1,i)-rat)<=1e-9)
{
//printf("%.3lf%.3lf\n",rat,tran(1,i));
s[0].push_back(i);
}
else s[1].push_back(i);
}
if(s[1].size()==0)return false;
if(s[1].size()==1)return true;
// for(int i=0;i<s[0].size();i++)
// printf("%d ",s[0][i]);
// printf("\n");
// for(int i=0;i<s[1].size();i++)
// printf("%d ",s[1][i]);
// printf("\n");
int len=s[1].size();
for(int i=1;i<len;i++)
{
if(fabs(tran(s[1][0],s[1][i])-rat)<=1e-9)continue;
else return false;
}
return true;
}
int main()
{
double rat;
int cnt;
while(scanf("%d",&n)!=EOF)
{
vis.clear();
flag=false;
cnt=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=3;i<=n;i++)
{
double temp;
if(i==3)
{
temp=tran(i,2);
rat=temp;
}
else
{
if(tran(i,2)==rat)cnt++;
}
}
if(cnt+3==n&&tran(1,2)!=rat)
{
printf("Yes\n");
continue;
}
for(int i=2;i<=n;i++)
{
double temp=tran(1,i);
if(vis[temp])continue;
vis[temp]=true;
if(check(temp,i))
{
//printf("what! :%d\n",i);
flag=true;
break;
}
}
if(flag)
printf("Yes\n");
else printf("No\n");
}
return 0;
}