CodeForces - 849B Tell Your World(简单题)

Tell Your World

题目链接:Tell Your World

题意:给你n个点的坐标,问是否有两条斜率相同但不重合的直线能够覆盖所有的点

思路:直线的斜率肯定为(点1和点2组成)直线1,(点2和点3组成)直线2和(点1和点3组成)直线3这三条直线中的一个

因此可以直接枚举三个斜率判断是否有符合条件的结果即可

代码:

#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;

int a[1010],n;
set<double>s;

bool judge(double k)
{
    s.clear();
    for(int i=1; i<=n; ++i)
        s.insert(a[i]*1.0-k*i);
    return s.size()==2;
}

int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
        scanf("%d",&a[i]);
    if(judge((a[2]-a[1])/1.0)||judge((a[3]-a[2])/1.0)||judge((a[3]-a[1])/2.0))
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}



比赛中写了一下,但是没想那么透。直接寻找是否存在符合条件的两条直线

代码:

#include<stdio.h>
#include<algorithm>
using namespace std;

const double eps=1e-8;
int a[1010],b[5];
struct point
{
    int x,y;
    point() {}
    point(int X,int Y)
    {
        x=X,y=Y;
    }
};

void swp(point &s1,point &s2)//交换两点
{
    point ss;
    ss.x=s1.x,ss.y=s1.y;
    s1.x=s2.x,s1.y=s2.y;
    s2.x=ss.x,s2.y=ss.y;
}

double ads(double x)//绝对值
{
    if(x<0)
        x=-x;
    return x;
}

int xmult(int x1,int y1,int x2,int y2,int x0,int y0)//计算 cross product(P1-P0)x(P2-P0)
{
    return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
}

bool dots_inline(int x1,int y1,int x2,int y2,int x3,int y3)//判三点是否共线
{
    return xmult(x1,y1,x2,y2,x3,y3)==0;
}

bool isParallel(point s1,point e1,point s2,point e2)//判断两条直线是否平行
{
    if(s1.x>s2.x)
        swp(s1,s2);
    if(e1.x>e2.x)
        swp(e1,e2);
    double y1=(s2.y-s1.y)*1.0/(s2.x-s1.x);
    double y2=(e2.y-e1.y)*1.0/(e2.x-e1.x);
    return ads(y1-y2)<eps;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
        scanf("%d",&a[i]);
    int tot=0;
    for(int i=3; i<=n; ++i)//1号点和2号点在一条直线上
    {
        if(!dots_inline(1,a[1],2,a[2],i,a[i]))//是否在第一条直线上
        {
            if(tot==2)//是否够两个点,确定第二条直线
            {
                if(!dots_inline(b[1],a[b[1]],b[2],a[b[2]],i,a[i]))//是否在第二条直线上
                {
                    ++tot;
                    break;
                }
            }
            else
            {
                b[++tot]=i;
                if(tot==2)//够两个点,确定了第二条直线
                {
                    if(!isParallel(point(1,a[1]),point(b[1],a[b[1]]),point(2,a[2]),point(b[2],a[b[2]])))//是否与第一条直线平行
                    {
                        ++tot;
                        break;
                    }
                }
            }
        }
    }
    if(tot==0)
        printf("No\n");
    else if(tot<=2)
        printf("Yes\n");
    else
    {
        b[1]=2;
        tot=1;
        for(int i=4; i<=n; ++i)//1号点和3号点在一条直线上
        {
            if(!dots_inline(1,a[1],3,a[3],i,a[i]))
            {
                if(tot==2)
                {
                    if(!dots_inline(b[1],a[b[1]],b[2],a[b[2]],i,a[i]))
                    {
                        ++tot;
                        break;
                    }
                }
                else
                {
                    b[++tot]=i;
                    if(tot==2)
                    {
                        if(!isParallel(point(1,a[1]),point(b[1],a[b[1]]),point(3,a[3]),point(b[2],a[b[2]])))
                        {
                            ++tot;
                            break;
                        }
                    }
                }
            }
        }
        if(tot<=2)
            printf("Yes\n");
        else
        {
            b[1]=1;
            tot=1;
            for(int i=4; i<=n; ++i)//2号点和3号点在一条直线上
            {
                if(!dots_inline(2,a[2],3,a[3],i,a[i]))
                {
                    if(tot==2)
                    {
                        if(!dots_inline(b[1],a[b[1]],b[2],a[b[2]],i,a[i]))
                        {
                            ++tot;
                            break;
                        }
                    }
                    else
                    {
                        b[++tot]=i;
                        if(tot==2)
                        {
                            if(!isParallel(point(2,a[2]),point(b[1],a[b[1]]),point(3,a[3]),point(b[2],a[b[2]])))
                            {
                                ++tot;
                                break;
                            }
                        }
                    }
                }
                if(tot>2)
                    break;
            }
            if(tot<=2)
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值