poj1175(线性规划)

之前的半平面交一直建立在多边形的基础上,因此遇到更一般的线性规划就显得有点措手不及。。

先讲一下线性规划的思路吧:

首先是把方程转化为半平面,这对用n^2的人来说并不难。。他们只需要用到直线方程。。

然而对使用nlogn的人来说,需要的反而是直线上的2点,这种逆变换感觉并没有什么优雅的姿势去解决。。

窝是这么解的。。首先先找出半平面的方向,即倾斜角k。。然后再找特殊点,在特殊点的基础之上分别加上cost和sint即可。。

然后倾斜角t要怎么找。。这里用图解可能会方便点。。。以Ax+By+C<0为例:


这里用到了直线方程的另外一种理解,点乘为定值的集合,这样可以通过向量n迅速找到和t的关系,将n旋转90度后倾斜角就已经是t了,所以t=atan2(-B,A)

特殊点窝取了y=0,考虑直线和y垂直的情况,需要特判一下才能取特殊点。。

转化为半平面后直接半平面交吧。。



然后来看看这题。。

设3个路程分别为a,b,c的话。。题目的要求应该是对每个人t,看是否满足

a/u[t]+b/w[t]+c/v[t]<=a/u[i]+b/w[i]+c/v[i]    i=1~n

当且仅当i==t等号成立

然后发现是3个未知数。。怕不是要来个三维的。。

其实很容易发现该式是个齐次式,同除c可以得到

a/c/u[t]+b/c/w[t]+1/v[t]<=a/c/u[i]+b/c/w[i]+1/v[i]

然后令x=a/c,y=b/c,直接三元降二元。。整理得

(u[i]-u[t])/u[i]/u[t]*y+(w[i]-w[t])/w[i]/w[t]*y+(v[i]-v[t])/v[i]/v[t]<=0

不推荐写1/u[i]-1/u[t]这类。。。貌似容易爆精度。。(评论区一大堆1e-16貌似就是这么来的。。

然后就剩下几个坑点了。。

要注意到题目要的是唯一胜者,交完出来是不是个点还需要特判。。。

另外。。x,y可能会非常大。。inf能开大就尽量开大。。




#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inf 10000005.0
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define ls T[i<<1]
#define rs T[i<<1|1]
#define op T[i]
#define mid (x+y>>1)
#define NM 105
#define nm 100498
#define pi 3.1415926535897931
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}

struct P{
	double x,y;
	P(double x=0,double y=0):x(x),y(y){}
	double operator*(const P&o){return x*o.y-y*o.x;}
	P operator-(const P&o){return P(x-o.x,y-o.y);}
}p[NM];
double dis(P o){return sqrt(sqr(o.x)+sqr(o.y));}
struct L{double k;P a,b;}l[NM];
int n,m,q[NM],qt,qh,tmp[NM];
double A,B,C,v[NM],u[NM],w[NM];

bool cmp(int x,int y){
	if(fabs(l[x].k-l[y].k)<eps)return (l[y].b-l[x].a)*(l[x].b-l[x].a)>eps;
	return l[x].k<l[y].k;
}
P intersect(L x,L y){
	double t1=(x.b-y.a)*(x.a-y.a),t2=(y.b-x.b)*(x.a-x.b);
	return P((y.a.x*t2+y.b.x*t1)/(t1+t2),(y.a.y*t2+y.b.y*t1)/(t1+t2));
}
bool judge(L a,L b,L c){return (a.b-a.a)*(intersect(b,c)-a.a)+eps<0;}
void cut(){
	sort(tmp+1,tmp+1+n+3,cmp);m=1;
	inc(i,2,n+3)if(fabs(l[tmp[i]].k-l[tmp[m]].k)>eps)tmp[++m]=tmp[i];
	mem(q);qh=1;qt=0;
	inc(k,1,m){
		int i=tmp[k];
		while(qh<qt&&judge(l[i],l[q[qt-1]],l[q[qt]]))qt--;
		while(qh<qt&&judge(l[i],l[q[qh+1]],l[q[qh]]))qh++;
		q[++qt]=i;
	}
	while(qh<qt&&judge(l[q[qt]],l[q[qh+1]],l[q[qh]]))qh++;
	while(qh<qt&&judge(l[q[qh]],l[q[qt-1]],l[q[qt]]))qt--;
}

int main(){
	//freopen("data.in","r",stdin);
	n=read();
	inc(i,1,n)u[i]=read(),w[i]=read(),v[i]=read();
	inc(i,1,n){
		bool f=true;
		inc(j,1,n)if(i!=j){
			A=(u[j]-u[i])/u[i]/u[j];
			B=(w[j]-w[i])/w[i]/w[j];
			C=(v[j]-v[i])/v[i]/v[j];
			if(fabs(u[i]-u[j])>eps)l[j].a=P(-C/A,0);
			else if(fabs(w[i]-w[j])>eps)l[j].a=P(0,-C/B);
			else{
				if(C+eps>0){f=false;break;}
				l[j].k=0;l[j].a=P(0,0);l[j].b=P(1,0);continue;
			}
			if(eps+u[j]>u[i]&&eps+w[j]>w[i]&&eps+v[j]>v[i]){f=false;break;}
			l[j].k=atan2(A,-B);
			l[j].b=P(l[j].a.x+cos(l[j].k),l[j].a.y+sin(l[j].k));
		}
		if(!f){puts("No");continue;}
		l[i].a=P(0,0);l[i].b=P(1,0);l[i].k=0;
		l[n+1].a=P(inf,0);l[n+1].b=P(inf,1);l[n+1].k=atan2(1.0,0.0);
		l[n+2].a=P(1,inf);l[n+2].b=P(0,inf);l[n+2].k=atan2(0.0,-1.0);
		l[n+3].a=P(0,1);l[n+3].b=P(0,0);l[n+3].k=atan2(-1.0,0.0);
		inc(i,1,n+3)tmp[i]=i;
		cut();
		//printf("%d %d %d\n",m,qh,qt);
		if(qt<=qh+1){puts("No");continue;}
		q[qt+1]=q[qh];m=0;double ans=0;
		inc(j,qh,qt)p[++m]=intersect(l[q[j]],l[q[j+1]]);
		inc(j,1,m)inc(k,j+1,m)ans=max(ans,dis(p[j]-p[k]));
		//printf("%lf\n",ans);
		if(ans>eps)puts("Yes");else puts("No");
	}
	return 0;
}






Triathlon
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 7470 Accepted: 1987

Description

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

Source

[Submit]   [Go Back]   [Status]   [Discuss]


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值