还剩8页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
GoneFishing算法详解及源码这道题其实难在读题上,因为这道题的细节太多,往往容易搞混,造成WA的情况,所以,学好英语还是有作用的解此题的主要方法是枚举+贪心刚开始的时候还没想到一个好方法,因为当前鱼最多的池塘是变化的,而题目所给描述里面的钓鱼又是有顺序的,即Johnstartsatlake1buthecanfinishatanylakehewants.Hecanonlytr__elfromonelaketothenextonebuthedoesnoth__etostopatanylakeunlesshewishesto.所以,不可能在池塘中间瞬移,所以贪心貌似不能用但转念一想,瞬移还是有可能的,当确定了结束池塘ep(endpond)之后(结束池塘由1枚举到n),我们便可以把从1到ep的交通费用从h中减去,然后用剩下的时间贪心即可因为在分析问题时,对于一个池塘,John在它上面什么时候钓鱼并不重要,所以可以先把John看成很聪明的人,然后假设他已经知道了在确定了结束池塘后,在每个池塘花多少时间使收益最大(实际上John是在贪心之后才知道的),这时我们就可以先减去交通费用,然后在1~ep的池塘中找现在的最大的即可这道题还比较容易WA,但最容易WA的地方还是全零的情况法2,没问题简单题直接枚举结束湖泊+贪心选择就可以了___可以贪心?(反正你要取的是最优解你可以假定自己知道最优解一路走过去的路上就直接取最优解就可以了)因为集训的时候这个题目莫名WA故再A一遍以解心头之恨!usingnamespa__std;不能用timeG++__多次faintGoneFishingSolution://byoyjpArt#includeiostream#includequeueusingnamespa__std;constintN=30;structnode{intnfidx;voidsetintnnintii{nf=nn;idx=ii;}};intnltimef[N]t[N]d[N]totfstay[N]beststay[N];typedefpriority_queuenodePQ;booloperatorconstnodeaconstnodeb{ifa.nf==b.nfreturna.idxb.idx;returna.nfb.nf;}int__in{intij;whilescanf%dnlnl{scanf%dtime;time*=12;int__xf=-1;fori=0;inl;i++scanf%df+i;fori=0;inl;i++scanf%dd+i;fori=0;inl-1;i++scanf%dt+i;fori=0;inl;i++{memsetstay0sizeofstay;totf=0;ifi0time-=t[i-1];nodenow;PQpq;forj=0;j=i;j++{now.setf[j]j;pq.pushnow;}forj=0;jtime;j++{now=pq.top;pq.pop;stay[now.idx]+=5;totf+=now.nf;now.nf-=d[now.idx];ifnow.nf0now.nf=0;pq.pushnow;}iftotf__xf{__xf=totf;memcpybeststaystaysizeofstay;}}printf%dbeststay
[0];fori=1;inl;i++printf%dbeststay[i];printf\nNumberoffishexpected:%d\n\n__xf;}return0;}includeiostreamusingnamespa__std;constintsize=26;intnhca;intf[size]t[size]d[size]tf[size];intans[size]tans[size]flag;int__in{intijksumtimetttnum__xsumnextmint1;whilecinn{ifn==0break;ca++;ifca1coutendl;cinh;__xsum=-100;h*=60;t1=0;fori=1;i=n;i++{cinf[i];tf[i]=f[i];}fori=1;i=n;i++cind[i];fori=1;in;i++cint[i];fori=1;i=n;i++ans[i]=tans[i]=0;fori=1;i=n;i++{t1+=t[i-1];time=h-t1*5/5;sum=0;forj=1;j=i;j++tans[j]=0;ifi==1d
[1]!=0{tans
[1]=time;tt=f
[1]/d
[1];iff
[1]%d
[1]tt++;iftime=ttsum=f
[1]+f
[1]-tt-1*d
[1]*tt/2;elsesum=f
[1]+f
[1]-time-1*d
[1]*time/2;time=0;}elseifi==1d
[1]==0{tans
[1]=time;sum=time*f
[1];time=0;}whiletime0{tnum=0;k=1;nextmin=0;flag=0;forj=1;j=i;j++iftnumf[j]tnum=f[j];forj=1;j=i;j++ifnextminf[j]f[j]!=tnumnextmin=f[j];forj=1;ji;j++iff[j]!=f[j+1]{flag=1;break;}iftnum==0{tans
[1]+=time;break;}ifflag==0||f
[1]==tnum{sum+=f
[1];f
[1]-=d
[1];iff
[1]0f
[1]=0;tans
[1]++;time--;continue;}forj=1;j=i;j++{iff[j]==tnumd[j]!=0time0{sum+=f[j];tans[j]++;f[j]-=d[j];time--;iftime0time=0;iff[j]0f[j]=0;}elseiff[j]==tnumd[j]==0time0{tans[j]+=time;sum+=time*f[j];time=0;break;}}}if__xsumsum{__xsum=sum;forj=1;j=i;j++ans[j]=tans[j];}forj=1;j=n;j++f[j]=tf[j];}fori=1;i=n;i++{coutans[i]*5;ifi!=ncout;elsecoutendl;}coutNumberoffishexpected:__xsumendl;}return0;}问题描述给定由n个整数(包含负整数)组成的序列a1a
2...an,求该序列子段和的最大值当所有整数均为负值时定义其最大子段和为0依此定义,所求的最优值为例如,当a1a2a3a4a5a6=-211-413-5-2时,最大子段和为一个简单算法int__xSumintnabestibestj{intsum=0;fori=1;i=n;i++forj=1;j=n;j++{intthissum=0;fork=i;k=j;k++thissum+=a[k];ifthissumsum{sum=thissum;besti=i;bestj=j;}}returnsum;}算法有3重循环,复杂性为On3由于有算法可作如下改进int__xSumintnabestibestj{intsum=0;fori=1;i=n;i++{intthissum=0;forj=i;j=n;j++{thissum+=a[j];ifthissumsum{sum=thissum;besti=i;bestj=j;}}}}改进后的算法复杂性为On2从问题的解的结构可以看出,它适合于用分治策略求解如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情形a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;a[1:n]的最大子段和为下面的形式A、B这两种情形可递归求得对于情形C,容易看出,a[n/2]与a[n/2+1]在最优子序列中因此,我们可以在a[1:n/2]和a[n/2+1:n]中分别计算出如下的s1和s2则s1+s2即为出现情形C时的最优值从而设计出下面所示的分治算法。