codeforces 849B
introduction
判断是否存在两条线,使得所有的点都落在这两条线上,并且每条线上至少有一个点
method
先取三个点,两两之间连线,则如果满足要求,三条线必有一条是结果中的直线。剩下的工作就是判断剩下的点是否在这条直线上,或者到直线的距离与第三个点到直线的距离相等,并且在同侧
useful knowledge
-
判断两个浮点数是否相等的方法是,将两个浮点数做差取绝对值,与预设的精度比较,例如
eps=1e-7
fabs(a-b)>1e-7如果为True,那么a大于b
为什么要这么做? -
直线表达成乘法的形式,可以避免引入浮点数
tips
- 只有在求点线距离的时候使用浮点数,其余时候使用long long
- 使用浮点数有很多问题,在可以使用整数的情况下优先使用整数
AC code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<cassert>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
typedef long long ll;
using namespace std;
const int MAXN=1e3+10;
const double eps=1e-7;
int n;
ll ycod[MAXN];
struct line{
ll A,B,C;
line(){}
line(ll x1,ll y1,ll x2,ll y2)
{
A=(y1-y2);
B=-(x1-x2);
C=y1*(x1-x2)-(y1-y2)*x1;
}
double dist(ll x,ll y)
{
return fabs(A*x+B*y+C)*1.0/(sqrt(A*A*1.0+B*B*1.0));
}
bool online(ll x,ll y)
{
return (A*x+B*y+C)==0;
}
bool sameside(ll x1,ll y1,ll x2,ll y2)
{
ll r1=A*x1+B*y1+C,
r2=A*x2+B*y2+C;
bool rt= (r1>0&&r2>0)||(r1<0&&r2<0);
// if(n==20)assert(rt==true);
return rt;
}
};
bool judge(line &l,ll idx)
{
double d=l.dist(idx,ycod[idx]);
for(int i=4;i<=n ;i++ ){
if(l.online(i,ycod[i]))continue;
if(!l.sameside(idx,ycod[idx],i,ycod[i]))return false;
double td=l.dist(i,ycod[i]);
if(fabs(td-d)>eps)return false;
}
return true;
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>n;
for(int i=1;i<=n ;i++ ){
cin>>ycod[i];
}
bool ok;
if(n==3){
line l1=line(1,ycod[1],2,ycod[2]);
ok =!l1.online(3,ycod[3]);
}
else {
line l1=line(1,ycod[1],2,ycod[2]);
line l2=line(2,ycod[2],3,ycod[3]);
line l3=line(1,ycod[1],3,ycod[3]);
if(l1.online(3,ycod[3])==false)
ok =judge(l1,3)||judge(l2,1)||judge(l3,2);
else {
double d=-1;
int idx=-1;
ok=true;
for(ll i=4;i<=n ;i++ ){
if(l1.online(i,ycod[i]))continue;
int td=l1.dist(i,ycod[i]);
if(d==-1)d=td,idx=i;
else {
if(l1.sameside(idx,ycod[idx],i,ycod[i])==false){
ok=false;
break;
}
else if(abs(d-td)>eps){
ok=false;
break;
}
}
}
if(idx==-1)ok=false;
}
}
if(ok)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}