CodeForces #431Div. 2 849B Tell your world 几何 暴力 枚举

版权声明:也还是请注明一下原地址,虽然写的不是很好。。。 https://blog.csdn.net/Good_night_Sion_/article/details/78206949

做这题之前首先大喊:

    骑士团参见公主殿下!!


然后这题目的题意是说给出n个点,判断这n个点是不是恰好在两条平行的直线上

题目会给出n个点的纵坐标,其中第i个点的横坐标是i

实际上我我觉得就算横坐标是给出的,也应该复杂度是一样的。O(n)


做法是枚举前三个点的状态,P1和P2在同一直线上,P1和P3在同一直线上,P2和P3在同一直线上。

对于任何一种情况来说,我们都可以把一条直线的斜率k和偏移量b求出来。然后对所有的点扫一遍,不在该直线上的点判断一下和另一个不在该直线上的点所连直线的斜率是不是等于已知直线。

最后注意特判一下所有点都在同一直线上的情况即可


此外一个小trick就是我把所有点都向左平移了一个单位,这样在枚举三种情况的时候偏移量b都会是整数

#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;
const double eps = 1E-7;
const int maxm=1010;

int n,arr[maxm];
bool check(double k,int b);

int main(){
    ios_base::sync_with_stdio(0);
    cin>>n;
    for(int i=0;i<n;++i)cin>>arr[i];
    cout<<(check(arr[1]-arr[0],arr[0])||check(arr[2]-arr[1],(arr[1]<<1)-arr[2])||check(0.5*(arr[2]-arr[0]),arr[0])?"Yes\n":"No\n");
    return 0;
}

bool check(double k, int b){
    int cnt=0,pos1=-1;
    for(int i=0;i<n;++i)
    if(arr[i]==1LL*k*i+b)
        ++cnt;
    else if(pos1==-1)
        pos1=i;
    else if(abs(k-(arr[i]-arr[pos1])*1.0/(i-pos1))>eps)
        return false;

    return cnt!=n;
}


猜你喜欢

转载自blog.csdn.net/Good_night_Sion_/article/details/78206949