POJ 1755 Triathlon (计算几何+半平面交解决线性规划)

该博客探讨如何使用计算几何和半平面交来解决POJ 1755 Triathlon比赛的线性规划问题。通过设定不同的赛道长度,判断每个选手是否有可能赢得比赛。博主提供了算法实现,包括建立不等式方程组和半平面交的计算方法,并给出了样例输入和输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Triathlon is an athletic contest consisting of three consecutive sections that should be completed as fast as possible as a whole. The first section is swimming, the second section is riding bicycle and the third one is running.

The speed of each contestant in all three sections is known. The judge can choose the length of each section arbitrarily provided that no section has zero length. As a result sometimes she could choose their lengths in such a way that some particular contestant would win the competition.
Input
The first line of the input file contains integer number N (1 <= N <= 100), denoting the number of contestants. Then N lines follow, each line contains three integers Vi, Ui and Wi (1 <= Vi, Ui, Wi <= 10000), separated by spaces, denoting the speed of ith contestant in each section.
Output
For every contestant write to the output file one line, that contains word "Yes" if the judge could choose the lengths of the sections in such a way that this particular contestant would win (i.e. she is the only one who would come first), or word "No" if this is impossible.
Sample Input
9
10 2 6
10 7 3
5 6 7
3 2 7
6 2 6
3 5 7
8 4 6
10 4 2
1 8 7
Sample Output
Yes
Yes
Yes
No
No
No
Yes
No
Yes

分别对每个人列一组不等式方程组再分别对每一组不等式方程组用半平面交求解
因为没规定跑道长度,我一开始就自己定义了一个很长的长度L,然后三个项目每一段长度为x,y,(L-x-y),
然后利用每一段的速度来求出每个人的总时间以此来列不等式方程组,但是这样wa了N发。。。
我们可以直接定义三段的长度为x,y,1( 可以看成以一定比例缩小之后,这样就稳了 ),然后列式子,半平面交

代码:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<functional>
#include<vector>
#include <map>
#include<cmath>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const double eps=1e-9;
const int MAXN=100+23;
#define point pair<double,double>
#define x first
#define y second
void output(point p[],int n)
{
    puts("******points:");
    for(int i=1;i<=n;i++)
    {
        printf("%.0f %.0f\n",p[i].x,p[i].y);
    }
}
double cross(point o,point a,point b)
{
    return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
double getarea(point p[],int n)
{
    double area=0;
    for(int i=2;i<n;i++)
    {
        area+=(p[i].x-p[1].x)*(p[i+1].y-p[1].y)-(p[i].y-p[1].y)*(p[i+1].x-p[1].x);
    }
    return area/2.0;
}
double dist(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void getline(double &a,double &b,double &c,point x1,point x2)
{
    a=(x1.y-x2.y);
    b=(x2.x-x1.x);
    c=-a*x1.x-b*x1.y;
}
point intersect(double a,double b,double c,point x1,point x2)
{
    double u=fabs(a*x1.x+b*x1.y+c);
    double v=fabs(a*x2.x+b*x2.y+c);
    return point((x1.x*v+x2.x*u)/(u+v),(x1.y*v+x2.y*u)/(u+v));
}
int n,last,now;
point p1[MAXN],p2[MAXN],p3[MAXN];
void cut(double a,double b,double c)
{
    now=0;
    //if(a==0&&b==0&&c<eps){last=0;return;}
    for(int i=1;i<=last;i++)
    {
        if((a*p2[i].x+b*p2[i].y+c)>eps)
        {
            p3[++now]=p2[i];
        }
        else
        {
            if((a*p2[i-1].x+b*p2[i-1].y+c)>eps)
            {
                p3[++now]=intersect(a,b,c,p2[i],p2[i-1]);
            }
            if((a*p2[i+1].x+b*p2[i+1].y+c)>eps)
            {
                p3[++now]=intersect(a,b,c,p2[i],p2[i+1]);
            }
        }
    }
    last=now;
    for(int i=1;i<=last;i++)p2[i]=p3[i];
    p2[last+1]=p3[1];p2[0]=p3[last];
}
inline void GuiZhengHua()
{
    //规整化方向,逆时针变顺时针,顺时针变逆时针
    for(int i = 1; i <=(n)/2; i++)
      swap(p1[i], p1[n-i]);//头文件加iostream
}
double length=1<<28;
double k1[100+23],k2[100+23],k3[100+23];
int main()
{
    while(scanf("%d",&n)!=-1)
    {
        for(int i=1;i<=n;i++)
        {
            double u,v,w;
            scanf("%lf%lf%lf",&u,&v,&w);
            k3[i]=w;
            k1[i]=u;
            k2[i]=v;
        }
        int m=n;
        for(int i=1;i<=m;i++)
        {
            p2[1]=point(0,0);
            p2[2]=point(0,length);
            p2[3]=point(length,length);
            p2[4]=point(length,0);
            p2[0]=p2[4];
            p2[5]=p2[1];
            last=4;
            double a,b,c;
            for(int j=1;j<=m;j++)
            {
                if(j==i)continue;
                a=(k1[i]-k1[j])/(k1[i]*k1[j]),b=(k2[i]-k2[j])/(k2[i]*k2[j]),c=(k3[i]-k3[j])/(k3[i]*k3[j]);
                cut(a,b,c);
                if(last==0)break;
            }
            if(getarea(p2,last)>=0)puts("No");
            else puts("Yes");
        }
    }
    return 0;
}
本人蒟蒻,如有错误,还望指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值