和菜鸟一起学算法之三分法求极值问题
2012-07-01 13:15
190 查看
午后的阳光,那么灿烂,如果不是温度过高,那么去西湖看看风景还是不错的。想着,现在西湖边应该是平静的湖面,加上无数知了在柳枝上演奏着交响曲吧。小看了下非诚勿扰,那男生为了女孩唐静付出了7年,唉,可是他错了,女孩根本不爱他,不过期间他的执着和付出,很让我感动,也许自己不太像他那样,才会让自己有现在的处境吧。也许吧。小感慨下。不过现在也挺好的,上上班,写写文章,然后天气凉快点还可以到处玩,杭州是个旅游休闲的好地方啊。扯远了,吃了饭回来,还是有些小感触啊。
回归正题,既然二分法讲完了,那么继续三分法吧。二分法适用于求单调的时候用的,就比如说排序好的数组,那是递增的或者递减的。如果像出现了下图二次函数那样的怎么求他的最值呢?
二分法早就失去了他的意义了。不过还是可以用三分法来实现的,就是二分中再来二分。比如我们定义了L和R,m=(L+R)/2,mm
=(mid+R)/2;如果mid靠近极值点,则R=mm;否则就是mm靠近极值点,则L=m;这样的话,极值还是可以求的。具体的还是看看题目吧。
zoj3203LightBulb
--------------------------------------------------------------------------------
TimeLimit:1SecondMemoryLimit:32768KB
--------------------------------------------------------------------------------
Comparedtowildleopard'swealthiness,hisbrothermildleopardisratherpoor.Hishouseisnarrowandhehasonlyonelightbulbinhishouse.Everynight,heiswanderinginhisincommodioushouse,
thinkingofhowtoearnmoremoney.Oneday,hefoundthatthelengthofhisshadowwaschangingfromtimetotimewhilewalkingbetweenthelightbulbandthewallofhishouse.Asuddenthoughtranthroughhismindandhewantedtoknowthemaximumlength
ofhisshadow.
Input
ThefirstlineoftheinputcontainsanintegerT(T<=100),indicatingthenumberofcases.
EachtestcasecontainsthreerealnumbersH,handDinoneline.Histheheightofthelightbulbwhilehistheheightofmildleopard.Disdistancebetweenthelightbulbandthewall.Allnumbers
areinrangefrom10-2to103,bothinclusive,andH-h>=10-2.
Output
Foreachtestcase,outputthemaximumlengthofmildleopard'sshadowinoneline,accurateuptothreedecimalplaces..
SampleInput
3
210.5
20.53
434
SampleOutput
1.000
0.750
4.000
题意很简单,就是人左右走动,求影子L的最长长度。
由图可知,当人走进时,当影子刚好没有投到墙上的时候,是最长的。接着影子到了墙上就变小了,所以可以用三分法来求最值。当然用高数的求导还是可以解决的,只是定义域要注意下。
这个基本上是模版吧,只是那个函数要自己去写,只要解决了这个函数,就一直让他循环求极值吧,差不多100次就可以找到这个点了。
再来看一道题目
其实就是汽车能不能拐弯的问题,告诉你X,Y,l,d判断是否能够拐弯,由下图可知,如果d大于X,Y的话,那么怎么样汽车也过不了。接着就是三分求下图那个最值了,如果到了这个地步,所求的h还是比Y小的话,那么肯定是可以拐弯的。
[/code]
TheBeet正在参加一场越野车大赛。比赛的场地如右图:共分三块,每一块地面的长宽均为N与M,但地表情况不同,越野车在这段路面上的最高速度也不同。蓝色线表示TheBeet可能的行车路线。
比赛的要求是要求选手从比赛的场地左上角驾车至右下角。TheBeet想知道如果他在所有路段都以最快速度行驶(不考虑加速阶段),最快能在多少时间内完成比赛。
Input
输入数据的第一行为两个正整数NM(N<=3000,M<=1000),表示一块路面的长和宽。
第二行为三个正整数S1,S2,S3(0<S1,S2,S3<=100),从上至下依次表示各个路面上越野车的最高速度。
Output
输出一个实数表示TheBeet最快能在多少时间内完成比赛。请输出一个尽可能精确的数字,控制误差在±0.000001的内。
SampleInput
3010
253
SampleOutput
13.7427361525
Hint
如果你的输出和结果的相差在0.000001之内,则认为是正确答案。
分析下该题,其实也是要求求最值,不过这个最值是满足两个地方的要求,想想和三分有什么关系呢?其实还是一样的,只是这里要用到两个三分了,不仅仅满足第一个要求,第二个要求也要一并给他满足了,接着这样的最值就是题目所要求的了。下面是搓搓的代码:
至此,三分法就是这样的了,很简单吧,总结下,就是要求出那个公式,然后调用那个框架。只要理解了原理,题目都是换汤不换药的。小憩片刻,还是回公司看看书去吧。这时代,不看书,不多学点东西,会被时代淘汰的。。。。。。
回归正题,既然二分法讲完了,那么继续三分法吧。二分法适用于求单调的时候用的,就比如说排序好的数组,那是递增的或者递减的。如果像出现了下图二次函数那样的怎么求他的最值呢?
二分法早就失去了他的意义了。不过还是可以用三分法来实现的,就是二分中再来二分。比如我们定义了L和R,m=(L+R)/2,mm
=(mid+R)/2;如果mid靠近极值点,则R=mm;否则就是mm靠近极值点,则L=m;这样的话,极值还是可以求的。具体的还是看看题目吧。
zoj3203LightBulb
--------------------------------------------------------------------------------
TimeLimit:1SecondMemoryLimit:32768KB
--------------------------------------------------------------------------------
Comparedtowildleopard'swealthiness,hisbrothermildleopardisratherpoor.Hishouseisnarrowandhehasonlyonelightbulbinhishouse.Everynight,heiswanderinginhisincommodioushouse,
thinkingofhowtoearnmoremoney.Oneday,hefoundthatthelengthofhisshadowwaschangingfromtimetotimewhilewalkingbetweenthelightbulbandthewallofhishouse.Asuddenthoughtranthroughhismindandhewantedtoknowthemaximumlength
ofhisshadow.
Input
ThefirstlineoftheinputcontainsanintegerT(T<=100),indicatingthenumberofcases.
EachtestcasecontainsthreerealnumbersH,handDinoneline.Histheheightofthelightbulbwhilehistheheightofmildleopard.Disdistancebetweenthelightbulbandthewall.Allnumbers
areinrangefrom10-2to103,bothinclusive,andH-h>=10-2.
Output
Foreachtestcase,outputthemaximumlengthofmildleopard'sshadowinoneline,accurateuptothreedecimalplaces..
SampleInput
3
210.5
20.53
434
SampleOutput
1.000
0.750
4.000
题意很简单,就是人左右走动,求影子L的最长长度。
由图可知,当人走进时,当影子刚好没有投到墙上的时候,是最长的。接着影子到了墙上就变小了,所以可以用三分法来求最值。当然用高数的求导还是可以解决的,只是定义域要注意下。
#include<stdio.h> intmain() { intt; scanf("%d",&t); while(t--) { doubleh,H,D; scanf("%lf%lf%lf",&H,&h,&D); doubleleft=0,right=D*h/H; intsize=100; doublemid,midmid,ans1,ans2; while(size--) { mid=(left+right)/2; midmid=(mid+right)/2; ans1=((h*D-H*mid)/(H-h)*H)/((h*D-H*mid)/(H-h)+D)+mid; ans2=((h*D-H*midmid)/(H-h)*H)/((h*D-H*midmid)/(H-h)+D)+midmid; if(ans1>ans2)right=midmid; elseleft=mid; } printf("%.3lf\n",ans1); } return0; }
这个基本上是模版吧,只是那个函数要自己去写,只要解决了这个函数,就一直让他循环求极值吧,差不多100次就可以找到这个点了。
再来看一道题目
hdu2438Turnthecorner
TimeLimit:3000/1000MS(Java/Others)MemoryLimit:32768/32768K(Java/Others) TotalSubmission(s):404AcceptedSubmission(s):103
ProblemDescription
Mr.Westboughtanewcar!Soheistravellingaroundthecity.Onedayhecomestoaverticalcorner.Thestreetheiscurrentlyinhasawidthx,thestreethewantstoturntohasawidthy.Thecarhasalengthlandawidthd.CanMr.Westgoacrossthecorner?
Input
Everylinehasfourrealnumbers,x,y,landw.Proceedtotheendoffile.
Output
Ifhecangoacrossthecorner,print"yes".Print"no"otherwise.
SampleInput
10613.54
10614.54
SampleOutput
yes
no
其实就是汽车能不能拐弯的问题,告诉你X,Y,l,d判断是否能够拐弯,由下图可知,如果d大于X,Y的话,那么怎么样汽车也过不了。接着就是三分求下图那个最值了,如果到了这个地步,所求的h还是比Y小的话,那么肯定是可以拐弯的。
[code]#include<cstdio>
#include<cmath>
constdoublepi=3.1415926535;
intmain()
{
doublex,y,l,w;
while(scanf("%lf%lf%lf%lf",&x,&y,&l,&w)!=EOF)
{
intsize=100;
doubleleft=0,right=pi/2;
doublemid=0,midmid=0,ans1,ans2;
if(x<w||y<w){printf("no\n");continue;}
while(size--)
{
mid=(left+right)/2;
midmid=(mid+right)/2;
ans1=(x-l*sin(mid)-w/cos(mid))/tan(mid);
ans2=(x-l*sin(midmid)-w/cos(midmid))/tan(midmid);
if(ans1<ans2)right=midmid;
elseleft=mid;
}
if(fabs(ans1)>y)printf("no\n");
elseprintf("yes\n");
}
return0;
}
[/code]
这两题几乎就是用了三分的模版,然后就是简单的公式推导,然后就可以很方便的实现了,接着我们来看看稍微复杂点的吧。
xmu1125.越野车大赛
DescriptionTheBeet正在参加一场越野车大赛。比赛的场地如右图:共分三块,每一块地面的长宽均为N与M,但地表情况不同,越野车在这段路面上的最高速度也不同。蓝色线表示TheBeet可能的行车路线。
比赛的要求是要求选手从比赛的场地左上角驾车至右下角。TheBeet想知道如果他在所有路段都以最快速度行驶(不考虑加速阶段),最快能在多少时间内完成比赛。
Input
输入数据的第一行为两个正整数NM(N<=3000,M<=1000),表示一块路面的长和宽。
第二行为三个正整数S1,S2,S3(0<S1,S2,S3<=100),从上至下依次表示各个路面上越野车的最高速度。
Output
输出一个实数表示TheBeet最快能在多少时间内完成比赛。请输出一个尽可能精确的数字,控制误差在±0.000001的内。
SampleInput
3010
253
SampleOutput
13.7427361525
Hint
如果你的输出和结果的相差在0.000001之内,则认为是正确答案。
分析下该题,其实也是要求求最值,不过这个最值是满足两个地方的要求,想想和三分有什么关系呢?其实还是一样的,只是这里要用到两个三分了,不仅仅满足第一个要求,第二个要求也要一并给他满足了,接着这样的最值就是题目所要求的了。下面是搓搓的代码:
#include<iostream>
#include<cstdio>
#include<cmath>
usingnamespacestd;
constdoublepi=3.141592654;
inlinedoubledis(doublex1,doubley1,doublex2,doubley2)
{
returnsqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
intmain()
{
doublen,m,a,b,c;
while(cin>>n>>m)
{
cin>>a>>b>>c;
doubleleft1=0,right1=pi/2;
doublemid1,midmid1,mid2,midmid2,ans1,ans11,ans2,ans3,ans4,ans5,ans44,ans55;
intsize=30;
while(size--)
{
mid1=(left1+right1)/2;
midmid1=(mid1+right1)/2;
ans1=dis((n-m/tan(mid1)),m,n,0);
ans11=dis((n-m/tan(midmid1)),m,n,0);
intsize1=30;
doubleleft2=0,right2=pi/2;
while(size1--)
{
mid2=(left2+right2)/2;
midmid2=(mid2+right2)/2;
ans2=dis((n-m/tan(mid1)),m,(n-m/tan(mid1)-m/tan(mid2)),2*m);
ans3=dis((n-m/tan(mid1)),m,(n-m/tan(mid1)-m/tan(midmid2)),2*m);
ans4=ans1/c+ans2/b+dis(0,3*m,(n-m/tan(mid1)-m/tan(mid2)),2*m)/a;
ans5=ans1/c+ans3/b+dis(0,3*m,(n-m/tan(mid1)-m/tan(midmid2)),2*m)/a;
if(ans4>ans5)left2=mid2;
elseright2=midmid2;
}
left2=0,right2=pi/2;
size1=30;
while(size1--)
{
mid2=(left2+right2)/2;
midmid2=(mid2+right2)/2;
ans2=dis((n-m/tan(midmid1)),m,(n-m/tan(midmid1)-m/tan(mid2)),2*m);
ans3=dis((n-m/tan(midmid1)),m,(n-m/tan(midmid1)-m/tan(midmid2)),2*m);
ans44=ans11/c+ans2/b+dis(0,3*m,(n-m/tan(midmid1)-m/tan(mid2)),2*m)/a;
ans55=ans11/c+ans3/b+dis(0,3*m,(n-m/tan(midmid1)-m/tan(midmid2)),2*m)/a;
if(ans44>ans55)left2=mid2;
elseright2=midmid2;
}
if(ans4>ans44)left1=mid1;
elseright1=midmid1;
}
printf("%.10lf\n",ans4);
}
return0;
}
至此,三分法就是这样的了,很简单吧,总结下,就是要求出那个公式,然后调用那个框架。只要理解了原理,题目都是换汤不换药的。小憩片刻,还是回公司看看书去吧。这时代,不看书,不多学点东西,会被时代淘汰的。。。。。。
相关文章推荐
- 和菜鸟一起学算法之三分法求极值问题
- 和菜鸟一起学算法之二分法求极值问题
- 和菜鸟一起学算法之二分法求极值问题
- 三分法——求解凸性函数的极值问题——czyuan原创
- 转载 - 三分法——求解凸性函数的极值问题
- 和菜鸟一起学linux总线驱动之i2c死锁问题
- 和菜鸟一起学linux总线驱动之i2c死锁问题
- 算法-三分法求极值
- 算法竞赛宝典 递推算法 极值问题
- 三分法(Ternary Search)求解凸(凹)函数的极值问题<题目篇>
- 三分法——求解凸性函数的极值问题
- 基因演算法解决函数极值问题-python版
- 【算法设计与数据结构】三分法:求单峰函数的极值
- 三分法求极值问题
- 【转】三分法——求解凸性函数的极值问题——czyuan原创
- 三分法——求解凸性函数的极值问题——czyuan原创
- 三分法——求解凸性函数的极值问题(转载自czyuan)
- 三分法——求解凸性函数的极值问题
- 和菜鸟一起学linux总线驱动之i2c死锁问题
- 三分法——求解凸性函数的极值问题——czyuan原创