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;
    }
    

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

  • 相关阅读:
    HDU 4611 Balls Rearrangement 数学
    Educational Codeforces Round 11 D. Number of Parallelograms 暴力
    Knockout.Js官网学习(简介)
    Entity Framework 关系约束配置
    Entity Framework Fluent API
    Entity Framework DataAnnotations
    Entity Framework 系统约定配置
    Entity Framework 自动生成CodeFirst代码
    Entity Framework CodeFirst数据迁移
    Entity Framework CodeFirst尝试
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6431746.html
Copyright © 2011-2022 走看看