HDU 4355 Party All the Time (三分算法的应用(含三分算法的讲解))

Party All the Time

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3351    Accepted Submission(s): 1050



Problem Description
In the Dark forest, there is a Fairy kingdom where all the spirits will go together and Celebrate the harvest every year. But there is one thing you may not know that they hate walking so much that they would prefer to stay at home if they need to walk a long way.According to our observation,a spirit weighing W will increase its unhappyness for S 3*W units if it walks a distance of S kilometers.
Now give you every spirit's weight and location,find the best place to celebrate the harvest which make the sum of unhappyness of every spirit the least.
 

Input
The first line of the input is the number T(T<=20), which is the number of cases followed. The first line of each case consists of one integer N(1<=N<=50000), indicating the number of spirits. Then comes N lines in the order that x [i]<=x [i+1] for all i(1<=i<N). The i-th line contains two real number : X i,W i, representing the location and the weight of the i-th spirit. ( |x i|<=10 6, 0<w i<15 )
 

Output
For each test case, please output a line which is "Case #X: Y", X means the number of the test case and Y means the minimum sum of unhappyness which is rounded to the nearest integer.
 

Sample Input
  
  
1 4 0.6 5 3.9 10 5.1 7 8.4 10
 

Sample Output
Case #1: 832
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4355

题意:小精灵不愿意走路,走路的话会使他们产生不高兴值,如果小精灵走的路是S体重是W那么他走S路程产生的不高兴值是ans=(S^3)*W;现在森林里要开一个庆祝会,给出各个小精灵的坐标(注意这里是一维的)和体重,求在哪里庆祝会使小精灵的不高兴值最小,输出这个最小的不高兴值。样例中第一行是样例个数,每个样例的第一行是小精灵的个数n,接下的n行是每个小精灵的坐标和体重。输出只有一个整数,即最小的不高兴值。注意输出格式。

题解:由于英语水平有限,刚开始读到这题时以为0.6是坐标(0.6)没敢做。。。后来读懂题后一时也是没有什么思路,然后想到了二分法,但是二分法一般是用来解单调的函数的,这个题明显不是单调函数,所以只好另外想办法。。。然后想到了分成三份选择性的更新某一端的值,结果再把细节弄好后居然真的AC了。。。赛后才发现居然用的是三分,原谅我比赛时不知什么是三分。。。。
三分算法适用于:凸性函数的极值问题,至于什么是凸性如图就是两种凸性函数。。。
这里以其中一种为例,比如该题以第一种为例。



如上图所示不断更新left与right,只要保证每次更新掉的是距极值(可能极大也可能极小)远的一侧就能保证每次更新后要去的极值一定在left和right之间,当left与right的差值小于题目要求的精度时(即约为相等时)left或right即为要求的极值点。
该题题目连接地址:http://acm.hdu.edu.cn/showproblem.php?pid=4355
详细细节见下面代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1e-5;//精度,判断left与right是否相等
const int MAXN=50100;
int n;
double p[MAXN];//记录每个位置
double w[MAXN];//记录每个W

double cal(double x){//按着题意公式计算消耗的函数
    double ans=0;
    for(int i=0;i<n;i++){
        double t=fabs(p[i]-x);
        ans+=t*t*t*w[i];
    }
    return ans;
}

double sear(double L,double R){//搜索函数,三分不断更新left或right,L为left,R为right
    double ll;double rr;//这里与上面的讲解不大一样,采用直接平均三分,ll和rr分别为中间三分点。
    while(R-L>eps){//注意浮点数不能直接判断相等,要用精度判断相等
        ll=(L*2+R)/3;//取出左侧三分点ll(ll=L+(R-L)/3经过化简就是该公式)
        rr=(L+2*R)/3;//取出右侧三分点rr(公式化简方法类似上面)
        if(cal(ll)>cal(rr)) L=ll;//更新左侧端点
        else R=rr;//更新右侧端点
    }
    return L;//返回极值点
}

int main(){
    int T;
    scanf("%d",&T);//样例个数
    int cas=1;//样例序号
    while(T--){
        scanf("%d",&n);
        double L=1111111,R=-1111111;
        for(int i=0;i<n;i++){//数据输入
            scanf("%lf%lf",&p[i],&w[i]);
            if(p[i]<L) L=p[i];//左侧端点初始化
            if(p[i]>R) R=p[i];//右侧端点初始化
        }
        double point=sear(L,R);//找出极值点point
        double ans=cal(point);//极值点代入公式计算得出最小消耗
        printf("Case #%d: %.0f\n",cas++,ans);//按格式输出
    }
    return 0;
}
要是大家哪里有不清楚的地方欢迎提问,要是有大神发现错误,望提出,感激不尽,欢迎大家的宝贵意见



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值