题意
有n 种工作,做1 单位时间的第i 种工作可以获得ai经验和bi 金钱,现在需要p 经验和q 金钱,问至少需要工作多久。工作时间可以不是整数
题解
一个显然的结论
如果你把一个点看做一个点
那么两个点(x1,y1)(x1,y1)和(x2,y2)(x2,y2)
那么他可以取到这两个点间的所有值
先新加入三个点(0,0)(0,0),(xmax,0)(xmax,0),(0,ymax)(0,ymax)
那么我们显然的可以先求出一个凸包
那么我们考虑一个点(p,q)(p,q)
他的最优方案
肯定是(0,0)(0,0)到(p,q)(p,q)这条射线和凸包的交
我们一直用这个点肯定是最优的
那么就除一下就出来了
然后我发现我以前凸包的板子有点问题,就是我没有把点去重,这样的话会导致凸包求出来不是对的。这个的话应该很容易举出反例吧。。对拍的时候发现了这个问题啊
CODE:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-7;
const int N=100005;
int n;
double p,q;
struct qq {double x,y;qq (){}qq (double _x,double _y){
x=_x;y=_y;}
}s[N];
int tot;
double mx=0,my=0;
double mul(qq x,qq y,qq z)
{double x1=x.x-z.x,y1=x.y-z.y;double x2=y.x-z.x,y2=y.y-z.y;return x1*y2-x2*y1;
}
double dis (qq x,qq y){
return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);}
bool cmp (qq x,qq y)
{if (abs(mul(x,y,s[1]))<eps) return dis(x,s[1])<dis(y,s[1]);return mul(x,y,s[1])>eps;
}
int sta[N],top;
void get ()//求一个凸包
{sta[1]=1;sta[2]=2;top=2;for (int u=3;u<=tot;u++){while (top>2&&mul(s[u],s[sta[top]],s[sta[top-1]])>eps) top--;sta[++top]=u;}tot=top;for (int u=1;u<=top;u++) s[u]=s[sta[u]];
}
bool check (int x)//0,0和这个的连线是否在他的下面
{return s[x].y*p<=s[x].x*q;
}
qq get (qq a,qq b,qq c,qq d)//求出这两条直线的交点
{A=mul(b,c,d),B=mul(c,a,d);double xx,yy;xx=b.x+(double)(a.x-b.x)*(double)A/(A+B);yy=b.y+(double)(a.y-b.y)*(double)A/(A+B);return qq(xx,yy);
}
int main()
{scanf("%d%lf%lf",&n,&p,&q);tot=1;s[tot]=qq(0,0);for (int u=1;u<=n;u++) {tot++;scanf("%lf%lf",&s[tot].x,&s[tot].y);mx=max(mx,s[tot].x);my=max(my,s[tot].y);}tot++;s[tot]=qq(mx,0);tot++;s[tot]=qq(0,my);sort(s+2,s+1+tot,cmp);int ToT=tot; tot=1;
for (int u=2;u<=ToT;u++)if (s[tot].x!=s[u].x||s[tot].y!=s[u].y)s[++tot]=s[u]; /* for (int u=1;u<=tot;u++)printf("%lf %lf\n",s[u].x,s[u].y);*/get();int l=1,r=tot-1;int lalal;//求出第一个点的连线是小于等于这个的 while (l<=r){int mid=(l+r)>>1;if (check(mid)) {lalal=mid;l=mid+1;}else r=mid-1;}if (s[lalal].y*p==s[lalal].x*q)//如果是在一条直线上{if (s[lalal].x==0) printf("%.8lf\n",(double)q/s[lalal].y);else printf("%.8lf\n",(double)p/s[lalal].x);}else{qq x=get(s[lalal],s[lalal+1],qq(p,q),qq(0,0));// printf("%lf %lf\n",s[lalal].x,s[lalal].y);// printf("%lf %lf\n",s[lalal+1].x,s[lalal+1].y);if (x.x>eps) printf("%.8lf\n",p/x.x);else printf("%.8lf\n",q/x.y);} return 0;
}