bzoj 3800: Saber VS Lancer (半平面交求解不等式组)

3800: Saber VS Lancer

Time Limit: 1 Sec   Memory Limit: 64 MB
Submit: 71   Solved: 27
[ Submit][ Status][ Discuss]

Description

铁人三项是一种运动项目,和字面意思一样,是让铁做的人(?)去做三个项目,必须连续完成,而且全程讲求速度。第一项是游泳,第二项是骑自行车,第三项是跑步。现在所有选手的三个项目的速度都是已知的。但是这次比赛中,裁判可以任意选择每一个项目的路程长度(假设没有一项长度为0)。但是这样显然会影响比赛排名……有时她会按某种方式选择,使得一些个别的选手能赢得竞赛。

Input

首行为运动员的人数N (1 ≤ N ≤ 100,80%的数据中n<=20),以下N行,每行含3个整数,Vi, Ui 和Wi (1 ≤ Vi, Ui, Wi ≤ 10000),用空格隔开,表示各人3个项目的速度。 

Output

对于每个运动员,都用一行输出,假如裁判以某种方式选择的路程会使得他赢(即第一个冲线,同时抵达不算赢),则输出“Yes”,否则输出“No”  。

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

HINT

Source

[ Submit][ Status][ Discuss]

题解:半平面交求解不等式组

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 103
#define eps 1e-16
#define inf 1000000000
using namespace std;
struct vector {
    double x,y;
    vector (double X=0,double Y=0){
        x=X,y=Y;
    }
}a1[N],p[N],tmp[N];
typedef vector point;
vector operator -(vector a,vector b){
    return vector (a.x-b.x,a.y-b.y);
}
vector operator +(vector a,vector b){
    return vector (a.x+b.x,a.y+b.y);
}
vector operator *(vector a,double t)
{
    return vector (a.x*t,a.y*t);
}
vector operator !=(vector a,vector b){
    return a.x!=b.x||a.y!=b.y;
}
struct data{
    point a,b;
}line[N];
double a[N],b[N],c[N];
int n,m;
void init()
{
    m=0;
    p[m++]=point(inf,inf);
    p[m++]=point(eps,inf);
    p[m++]=point(eps,eps);
    p[m++]=point(inf,eps);
}
int dcmp(double x)
{
    if (fabs(x)<eps) return 0;
    return x<0?-1:1;
}
double cross(vector a,vector b)
{
    return a.x*b.y-a.y*b.x;
}
point glt(point a,point a0,point b,point b0)
{
    double a1,b1,c1,a2,b2,c2;  
    a1 = a.y - a0.y;  
    b1 = a0.x - a.x;  
    c1 = cross(a,a0);  
    a2 = b.y - b0.y;  
    b2 = b0.x - b.x;  
    c2 = cross(b,b0);  
    double d = a1 * b2 - a2 * b1;  
    return point((b1 * c2 - b2 * c1) / d,(c1 * a2 - c2 * a1) / d);   
}
void cut(point a,point b)
{
    int cnt=0;
    memset(tmp,0,sizeof(tmp));
    for (int i=0;i<m;i++){
        double c=cross(b-a,p[i]-a);
        double d=cross(b-a,p[(i+1)%m]-a);
        if (dcmp(c)>=0) 
          tmp[cnt++]=p[i];
        if (dcmp(c)*dcmp(d)<0) 
         tmp[cnt++]=glt(a,b,p[i],p[(i+1)%m]);
    }
    m=0;
    for (int i=0;i<cnt;i++) 
     if (m==0 || (tmp[i].x!=p[m-1].x||tmp[i].y!=p[m-1].y)) 
       p[m++]=tmp[i];
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
    for (int i=1;i<=n;i++){
        int k=0;
        bool mark=true;
        for (int j=1;j<=n;j++){
            if (i==j) continue;
            double nowa=1.0/a[j]-1.0/a[i];
            double nowb=1.0/b[j]-1.0/b[i];
            double nowc=1.0/c[j]-1.0/c[i];
            if (dcmp(nowa)==0&&dcmp(nowb)==0) {
                if (dcmp(nowc)>0) continue;
                else {
                    mark=false;
                    break;
                }
            }
            k++;
            if (dcmp(nowb)==0) {
                double t=-nowc/nowa;
                line[k].a.x=t; line[k].b.x=t;
                line[k].a.y=1; line[k].b.y=2;
                if (dcmp(nowa)>0) swap(line[k].a,line[k].b);
                continue;
            }
            line[k].a.x=1;
            line[k].a.y=-(nowa+nowc)/nowb;
            line[k].b.x=2;
            line[k].b.y=-(nowa*2.0+nowc)/nowb;
            if (dcmp(nowb)<0) swap(line[k].a,line[k].b);
        }
        if (!mark){
            printf("No\n");
            continue;
        }
        init();
        for (int  j=1;j<=k;j++)
         cut(line[j].a,line[j].b);
        double area=0; p[m]=p[0];
        for (int j=1;j<m;j++) area+=cross(p[j]-p[0],p[j+1]-p[0]);
        area=fabs(area);
        if (m>2&&dcmp(area)>0) printf("Yes\n");
        else printf("No\n");
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值