POJ 1755 判断线性区域是否存在可行区域

题意 : 给你每个人在每一段的速度,让你求出是否存在一种路程的安排使得这个人可以赢得这场比赛

题解 :可以去列方程组,然后发现是一个三维的变元,但是发现有一个变元,可以除过去就成了一个二元方程就是一个二维平面然后判断一个线性方程式组是否存在可行域.

发一个求线性区域的可行区域的模版

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps = 1e-16;
const double inf = 1e9 + 5;
const int maxn = 1505;
struct Point{
    double x,y;
}p[maxn],tp[maxn],q[maxn];
struct Node{
    double u,v,w;
}z[maxn];
double ab (double x) {return x > 0 ? x : -x;}
double xmul(Point p0,Point p1,Point p2){
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
Point Intersection(Point p1,Point p2,double a,double b,double c){
    double u = ab(a*p1.x+b*p1.y+c);
    double v = ab(a*p2.x+b*p2.y+c);
    Point t;
    t.x=(p1.x*v+p2.x*u)/(u+v);t.y=(p1.y*v+p2.y*u)/(u+v);
    return t;
}
double Get_area(Point p[],int n){
    double area=0;
    for(int i=2;i<n;i++)
        area+=xmul(p[1],p[i],p[i+1]);
    return -area/2.0;
}
void Cut(double a,double b,double c,Point p[],int &cnt){
    int tmp=0;
    for (int i=1;i <= cnt;i++){
        if(a*p[i].x+b*p[i].y+c>-eps) tp[++tmp]=p[i];
        else{
            if(a*p[i-1].x+b*p[i-1].y+c>eps)
                tp[++tmp]=Intersection(p[i-1],p[i],a,b,c);
            if(a*p[i+1].x+b*p[i+1].y+c>eps)
                tp[++tmp]=Intersection(p[i],p[i+1],a,b,c);
        }
    }
    for(int i=1;i<=tmp;i++)
        p[i]=tp[i];
    p[0]=p[tmp];p[tmp+1]=p[1];
    cnt=tmp;
}
int slove(int n,int idx) {
    p[1].x=0;p[1].y=0;
    p[2].x=0;p[2].y=inf;
    p[3].x=inf;p[3].y=inf;
    p[4].x=inf;p[4].y=0;
    p[0]=p[4];p[5]=p[1];
    int cnt=4;
    for(int i=0;i<n;i++){
        if(i==idx) continue;
        double a,b,c;
        a=(z[idx].u-z[i].u)/(z[idx].u*z[i].u);
        b=(z[idx].v-z[i].v)/(z[idx].v*z[i].v);
        c=(z[idx].w-z[i].w)/(z[idx].w*z[i].w);
        if(a==0 && b==0&&c<eps) return 0;
        Cut(a,b,c,p,cnt);
    }
    return ab (Get_area(p, cnt)) >= eps;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++)
            scanf("%lf%lf%lf",&z[i].u,&z[i].v,&z[i].w);
        for(int i=0;i<n;i++)
            puts(slove(n,i)?"Yes":"No");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值