以前听到三分法的时候总是一脸懵逼,心想三分了怎么继续确定区间,三分的两个点又怎么确定?想破头也想不出来。
今天偷偷看了西工大某美女姐姐(好吧,虽然没见过,就这么叫吧)的博客,发现三分竟然是有特定条件的……
先来说说三分法,据前人的研究,三分法适用于凹凸函数求它的凹凸点。与二分法不同的是三分法将mid点与r点的中间点也并入讨论,设其为mmid点。
显然,mmid>mid.
以凹函数为例子,求它的最大值点。当f(mid)>f(mmid)时,mmid点一定在最大值点的右端,否则mmid将小于mid,矛盾。此时可以将R端点移动到mmid点。
同理,当f(mid)<f(mmid)时,将L端点移动到mid点,可以保证是向最大值点逼近。
Party All the Time
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4945 Accepted Submission(s): 1561
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.
1 4 0.6 5 3.9 10 5.1 7 8.4 10
Case #1: 832
题意,在一排路上有n个ctr,每个ctr有一个重量,已知将在x[i]点处的ctr移动到x点需要花费(x[i]-x)^3*w[i]的力气,现求出将所有ctr移动到一点的最小费用
首先证明三分的可行性:
这个题目的费用函数可以写为∑fabs(x[i]-x)^3*w[i],(i=1,2……n)考虑(x[i]-x)^3的凹凸性,求二阶导数为-6x-2x[i],显然小于零,此为凸函数,有最小值。
代码
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int ca,t,i,j,k,m,n;
double x[50004],w[50004];
double f(double x1)
{ double sum=0;
for(i=1;i<=n;i++)
{ double po=fabs(x[i]-x1);
sum+=w[i]*po*po*po;
}
return sum;
}
int main()
{
scanf("%d",&t);
for(ca=1;ca<=t;ca++)
{
scanf("%d",&n);
memset(x,0,sizeof(x));
memset(w,0,sizeof(w));
for(i=1;i<=n;i++)scanf("%lf%lf",&x[i],&w[i]);
double l=x[1],r=x[n];
double mid=(l+r)/(2.0);
double mmid=(r+mid)/(2.0);
while(r-l>1e-7)
{
if(f(mid)<f(mmid))
{
r=mmid;
mid=(l+r)/(2.0);
mmid=(r+mid)/(2.0);
}
else
{
l=mid;
mid=(l+r)/(2.0);
mmid=(r+mid)/(2.0);
}
}
printf("Case #%d: %.0f\n",ca,min(f(l),f(r)));
}
return 0;
}
好吧,还是想吐槽一下最近的悲惨生活……先是手机被偷……再是电脑硬盘即将寿终正寝(写这篇博客的时候硬盘又卡住了好几次orz)……今天又听闻家里座机半月前被电信当成无人号码卖给了另外一家人,现在能正确打电话回家都要算概率……数学建模得了个谢谢参与,数学分析什么都不会,初等玄学(高等代数)依然玄学中,物理不看书做题战斗力成0,近代史完全记不下来,昨天又听闻我们这渣学校的人,没有国家级以上的奖项,保研的时候好985看都不看,就算考研进复试也会被刷下来orz……前途一片惨淡啊……以后就靠现在多攒点钱在学校门口支个摊卖炸串把……不过吧,每当感到悲惨的时候总有那什么能让我依然对生活充满希望