• HDU 4355 Party All the Time (三分求凸函数极值)


    题目大意:有n个精灵位于一维坐标轴上, 每个精灵有一个权值w, 每个精灵走到另一个位置耗费能量S^3 * w。(s是两点间距离)。现在精灵要聚会, 求选取一点,使所有精灵到这点浪费能量之和最小。   分析:设这点的位置是x,精灵位置是pi,则浪费能量值和f = sigma[(pi-x)^3*wi].其中x是变量. 通过对这个函数求二次导可以发现,这个函数是一个下凸函数.可以用三分做.   具体的三分方法如图: 凸函数:   凸函数三分 凹函数:   凹函数三分   三分求凸函数极值模板:  
    //如果一个解函数的二次导恒>0(or <0),则该函数为凸函数.
    
    //精度模板
    const double eps = 1e-6;
    bool dy(double x,double y)  {   return x > y + eps;} 		// x > y
    bool xy(double x,double y)  {   return x < y - eps;} 		// x < y
    bool dyd(double x,double y) {   return x > y - eps;} 		// x >= y
    bool xyd(double x,double y) {   return x < y + eps;}     	// x <= y
    bool dd(double x,double y)  {   return fabs( x - y ) < eps;}    // x == y
    
    double cal(double pos){
        /* 根据题目的意思计算 */
    }
    
    double solve(double left, double right){
        while(xy(left, right)){
            double mid = DMID(left, right);
            double midmid = DMID(mid, right);
            double mid_area = cal(mid);
            double midmid_area = cal(midmid);
            if (xyd(mid_area, midmid_area))     //下凸函数,上凸函数用dyd(mid_area, midmid_area)
                right = midmid;
            else
                left = mid;
        }
        return left;
    }
    
      HDU 4355 代码:  
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MID(x,y) ((x+y)>>1)
    #define DMID(x,y) ((x+y)/2)
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    const int N = 50002;
    double x[N], w[N];
    int n;
    
    //二分精度模板
    const double eps = 1e-6;
    bool dy(double x,double y)  {   return x > y + eps;} 		// x > y
    bool xy(double x,double y)  {   return x < y - eps;} 		// x < y
    bool dyd(double x,double y) {   return x > y - eps;} 		// x >= y
    bool xyd(double x,double y) {   return x < y + eps;}     	// x <= y
    bool dd(double x,double y)  {   return fabs( x - y ) < eps;}    // x == y
    
    double cal(double pos){
        /* 根据题目的意思计算 */
        double res = 0.0;
        for (int i = 0; i < n; i ++){
            res += abs(pos - x[i]) * abs(pos - x[i]) * abs(pos - x[i]) * w[i];
        }
        return res;
    }
    
    double solve(double left, double right){
        while(xy(left, right)){
            double mid = DMID(left, right);
            double midmid = DMID(mid, right);
            double mid_area = cal(mid);
            double midmid_area = cal(midmid);
            if (xyd(mid_area, midmid_area))     //下凸函数,上凸函数dyd(mid_area, midmid_area)
                right = midmid;
            else
                left = mid;
        }
        return left;
    }
    
    int main(){
        int t;
        scanf("%d", &t);
        for (int caseo = 1; caseo <= t; caseo ++){
            scanf("%d", &n);
            double low = -1000000, high = 1000000;
            for (int i = 0; i < n; i ++){
                scanf("%lf %lf", &x[i], &w[i]);
                low = min(low, x[i]);
                high = max(high, x[i]);
            }
    
            printf("Case #%d: %.0f\n", caseo, (cal(solve(low, high))));
        }
    	return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    PAT 1010. 一元多项式求导 (25)
    PAT 1009. 说反话 (20) JAVA
    PAT 1009. 说反话 (20)
    PAT 1007. 素数对猜想 (20)
    POJ 2752 Seek the Name, Seek the Fame KMP
    POJ 2406 Power Strings KMP
    ZOJ3811 Untrusted Patrol
    Codeforces Round #265 (Div. 2) 题解
    Topcoder SRM632 DIV2 解题报告
    Topcoder SRM631 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114015.html
Copyright © 2020-2023  润新知