codeforces 849B Tell Your World

B. Tell Your World
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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 ( - 109 ≤ yi ≤ 109) — 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>=3),问是否存在两平行直线经过所有点(不能重合),点的坐标为(i,a[i])

最后一分钟写完交了,只想到了暴力的做法,开始以为暴力的复杂度为n^3,后来一想复杂度撑死也才n^2,开始算错了复杂度不敢写暴力

将直线分成两组,两组的斜率要相等且不在一条直线上,我的做法是首先判断是否在一条直线上,在将直线分成两组判断斜率是否相等

代码较搓


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<cmath>
#include<vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pi acos(-1.0)
#define eps 1e-10
#define pf printf
#define sf scanf
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define e tree[rt]
#define _s second
#define _f first
#define all(x) (x).begin,(x).end
#define mem(i,a) memset(i,a,sizeof i)
#define for0(i,a) for(int (i)=0;(i)<(a);(i)++)
#define for1(i,a) for(int (i)=1;(i)<=(a);(i)++)
#define mi ((l+r)>>1)
#define sqr(x) ((x)*(x))

const int inf=0x3f3f3f3f;
int n,a[1010],b[1010];
bool vis[1010];

int main()
{
    while(~sf("%d",&n))
    {
        int tag=0;
        for1(i,n)
            sf("%d",&a[i]);//下标为横坐标
        double t1=(double)a[2]-a[1];
        double t2=(double)a[3]-a[2];
        int i;
        for(i=4;i<=n;i++)
        {
            double p=(double)(a[i]-a[2])/(i-2);
            if(p!=t2)
                break;
        }
        if(i==n+1&&t1==t2)//判断是否在一条在直线上
        {
            puts("No");
            continue;
        }
        else if(i==n+1&&t1!=t2)//和第一个点和第二个点的斜率和后面点的斜率不相等,第二个点和后面的点在一条直线上,一个点可构成任意斜率的直线
        {
            puts("Yes");
            continue;
        }
        for(int i=2;i<=n;i++)
        {
            int num=0;
            mem(vis,0);
            vis[1]=1;
            vis[i]=1;//标记为1表示斜率和第一个点在一组里,别的在另外一组
            double q1=(double)(a[i]-a[1])/(i-1);//计算第一组的斜率
            for(int j=i+1;j<=n;j++)
            {
                double q2=(double)(a[j]-a[1])/(j-1);
                if(q2==q1)vis[j]=1;//和第一个点的斜率等于第一组的斜率,分在第一组
            }
            for(int i=1;i<=n;i++)//将另一组的的点预处理一下
                if(!vis[i])
                    b[++num]=i;
            if(num==1)//只有一个点不在第一组,经过这个点的斜率任意,说明可以满足条件
            {
                tag=1;
                break;
            }
            double w1=(double)(a[b[2]]-a[b[1]])/(b[2]-b[1]);判断第二组的点是否在一条直线上
            int j;
            for(j=3;j<=num;j++)
            {
                double w2=(double)(a[b[j]]-a[b[1]])/(b[j]-b[1]);
                if(w2!=w1)
                    break;
            }
            if(j==num+1&&w1==q1)//第二组都在一条直线上,且斜率等于第一组
            {
                tag=1;
                break;
            }
        }
        puts(tag?"Yes":"No");
    }
    return 0;
}


这样的写法代码比较长而且很不好懂,看了别人的代码之后觉得精简很多,原文链接为:http://blog.csdn.net/mr_treeeee/article/details/77802946,其实只用考虑前三个点就行了,前三个点中一定有两个点的斜率为平行直线的斜率(想想为什么),把前三个点两两构成的斜率带进去就行


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<cmath>
#include<vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pi acos(-1.0)
#define eps 1e-10
#define pf printf
#define sf scanf
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define e tree[rt]
#define _s second
#define _f first
#define all(x) (x).begin,(x).end
#define mem(i,a) memset(i,a,sizeof i)
#define for0(i,a) for(int (i)=0;(i)<(a);(i)++)
#define for1(i,a) for(int (i)=1;(i)<=(a);(i)++)
#define mi ((l+r)>>1)
#define sqr(x) ((x)*(x))

const int inf=0x3f3f3f3f;
int n,a[1010];

bool check(double k)
{
    int p=-1;
    for(int i=2;i<=n;i++)
    {
        if((i-1)*k==a[i]-a[1])continue;
        if(p==-1)p=i;//不想等分在另一组
        else if(k*(p-i)!=a[p]-a[i])return 0;//和两个的斜率都不相等,不满足条件
    }
    return p!=-1;//判断是否在一条直线上
}

int main()
{
    while(~sf("%d",&n))
    {
        for1(i,n)
            sf("%d",&a[i]);
        if(check(a[2]-a[1])||check((a[3]-a[1])/2.0)||check(a[3]-a[2]))
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值