Bzoj4570--Scoi2016妖怪

把每一个妖怪看出平面上的一个点(x,y),场地参数k=-a/b;

那么每个妖怪的战斗力即为过点(x,y)斜率为k的直线与坐标轴的交点的和

稍微画下图可以看出如果是最大战力的妖怪一定是在所有点所形成的右上凸包上

维护一个凸包,枚举凸包每一个点是最强妖怪时的最弱战力

要使一个点所形成的是最强战力,那么有过这个点i的斜率k i-1<k i<k i+1,算出每个点的最佳斜率k',如果k'满足条件则代入k'更新答案,再用i与i+1的斜率更新一下答案

代码如下 :

#include<bits/stdc++.h>
#define MAXN 1000005
#define MAXM 150005
#define fix 40000
#define INF 1000000000
#define eps 1e-9
#define LL long long
using namespace std;

struct P{
    double x,y;
    bool operator < (P b) const {return x>b.x;}
    double comp() {return x+y+2*sqrt(x*y);}
}p[MAXN],tb[MAXN];
double k[MAXN],ans=INF; int n,top,ed; inline double cross(P a,P b,P c) { a.x-=b.x;a.y-=b.y;b.x-=c.x;b.y-=c.y; return b.x*a.y-b.y*a.x; } inline double Get_K(P a,P b) {return (a.y-b.y)/(a.x-b.x);} int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } sort(p+1,p+1+n); for(int i=1;i<=n;i++) { while(top>1&&cross(p[i],tb[top],tb[top-1])<0) top--; tb[++top]=p[i]; } k[0]=-INF; for(int i=1;i<=top;i++) { k[i]=Get_K(tb[i+1],tb[i]); ed=i;if(k[i]>=0) break; } k[ed]=-eps; for(int i=1;i<=ed;i++) { double mk=-sqrt(tb[i].y/tb[i].x),cg=INF,he; if(mk>k[i-1]&&mk<k[i]) cg=tb[i].comp(); he=tb[i].x+tb[i].y-k[i]*tb[i].x-tb[i].y/k[i]; cg=cg>he?he:cg;ans=ans>cg?cg:ans; } printf("%.4lf",ans); return 0; } 

 

为了方便是把右上凸包的首尾斜率设置了一下

转载于:https://www.cnblogs.com/ihopenot/p/5910902.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值