zoukankan      html  css  js  c++  java
  • bzoj 4570: [Scoi2016]妖怪 凸包

    题目大意:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4570

    题解

    我们知道如果一个怪物要取到攻击力的最大值,那么一定是把防御力都转化了
    所以我们可以把题目转化成这个式子
    (min(max(atk + den + frac{a}{b}dnf + frac{b}{a}atk)))
    我们设(k = -frac{b}{a})
    那么上式变为了(min(max(atk + den - (frac{1}{k}dnf + k*atk))))
    右侧括号里是对勾函数的形式,我们由数学知识得(k = -sqrt{frac{dnf}{atk}})时取得最值
    现在我们尝试把所有的点映射到二维平面
    设点((x,y)),假设通过了一条斜率为(k(k < 0))的直线
    我们通过计算发现这个直线的横纵截距之和即为我们上面的计算式
    而当(k = -sqrt{frac{dnf}{atk}})横纵截距之和最小
    所以问题转化成了为二维平面上的一些点确定一些平行线通过这些点使得最大的横纵截距之和最小
    我们知道最大的条直线一定是通过上凸壳上的点的
    所以我们枚举上凸壳上的点即可

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(double &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
    inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
    const int maxn = 1000010;
    const double eps = 1e-8;
    struct Point{
    	double x,y;
    	Point(double a = 0,double b = 0){x=a;y=b;}
    };
    typedef Point Vector;
    inline Vector operator + (const Vector &a,const Vector &b){return Vector(a.x+b.x,a.y+b.y);}
    inline Vector operator - (const Vector &a,const Vector &b){return Vector(a.x-b.x,a.y-b.y);}
    inline double operator * (const Vector &a,const Vector &b){return a.x*b.x + a.y*b.y;}
    inline double operator / (const Vector &a,const Vector &b){return a.x*b.y - a.y*b.x;}
    inline double min_p(const Point &x){return -sqrt(x.y/x.x);}
    inline int dcmp(const double x){
    	if(x < eps && x > -eps) return 0;
    	return x > 0 ? 1 : -1;
    }
    inline double slope(const Point &a,const Point &b){
    	if((dcmp(a.x) == 0) && (dcmp(a.y) == 0)) return 1e10;
    	if((dcmp(b.x) == 0) && (dcmp(b.y) == 0)) return -1e10;
    	if(dcmp(a.x-b.x) == 0 ) return 1e10;
    	return (b.y - a.y)/(b.x - a.x);
    }
    inline bool cmp(const Point &a,const Point &b){
    	return dcmp(a.x - b.x) == 0 ? a.y < b.y : a.x < b.x;
    }
    inline double calc(const Point &p,const double k){
    	if(k >= 0 ) return 1e10;
    	return p.x + p.y - k*p.x - p.y/k;
    }
    Point p[maxn],ch[maxn];
    int n,m;
    inline void convex(){
    	m = 0;ch[++m] = p[1];
    	for(int i=2;i<=n;++i){
    		while(m > 1 && dcmp((ch[m] - ch[m-1])/(p[i] - ch[m])) >= 0) m -- ;
    		ch[++m] = p[i];
    	}swap(n,m);swap(p,ch);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) read(p[i].x),read(p[i].y);
    	if(n == 1){printf("%.4lf
    ",calc(p[1],min_p(p[1])));return 0;}
    	sort(p+1,p+n+1,cmp);convex();
    	double ans = 1e10;
    	double k1,k2,k;
    	k2 = slope(p[1  ],p[2]);k=min_p(p[1]);if(k>=k2) ans=min(ans,calc(p[1],k));  
    	k1 = slope(p[n-1],p[n]);k=min_p(p[n]);if(k<=k1) ans=min(ans,calc(p[n],k));  
    	ans=min(ans,calc(p[n],k1));  
    	for(int i=2;i<n;++i){
    		k = min_p(p[i]),k1 = slope(p[i-1],p[i]),k2 = slope(p[i],p[i+1]);
    		ans = min(ans,calc(p[i],k1));
    		if(dcmp(k-k1) <= 0 && dcmp(k-k2) >= 0 ) ans = min(ans,calc(p[i],k));
    	}printf("%.4lf
    ",ans);
    	getchar();getchar();
    	return 0;
    }
    

    恕我直言...网上的一些代码和我对拍根本拍不上。。。
    而且它们好多互相都拍不上。。。
    反正我写过了\\

  • 相关阅读:
    贪心+stack Codeforces Beta Round #5 C. Longest Regular Bracket Sequence
    暴力/DP Codeforces Beta Round #22 (Div. 2 Only) B. Bargaining Table
    DFS Codeforces Round #299 (Div. 2) B. Tavas and SaDDas
    二分搜索 Codeforces Round #299 (Div. 2) C. Tavas and Karafs
    水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas
    数学 2015百度之星初赛2 HDOJ 5255 魔法因子
    贪心/数学 2015百度之星资格赛 1004 放盘子
    模拟 2015百度之星资格赛 1003 IP聚合
    rails安装使用版本控制器的原因。
    ActiveStorage. 英文书Learnrails5.2的案例,看如何放到云上。
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6431746.html
Copyright © 2011-2022 走看看