- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
递推法在解题方法和解题思维上的使用
东风七中叶飞
对于信息学奥林匹克联赛的题目来说有人讲简单,有人讲难。为什么会有如此大的差别呢?我觉得如何选择正确的思维方式是能否顺利解决问题的关键。递推法是常用的解题方法之一,我认为它也是最好用的方法。首先我们来看一下第一题。
题目是这样的:丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后去发觉原来在简单的规则下想要赢得这个游戏并不那末容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为个部分,各部分内的数字相加,相加所得的m个结果对10去模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或最小。
例如,对于下面这圈数字(n=4,m=2)
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均取非负值。
丁丁请你编写程序帮他赢得这个游戏。
对于这题给人的第一感觉就是用穷举法,把每个情况都探到即可解题。但你要仔细看一下题目要求就会发现问题所在。题目要求n(1≤n≤50)和m(1≤m≤9)粗略估计一下所可能出现的情况应为429即是4.06×1014次。这样是无法在规定的时间里完成。那么如何解决呢?答案就是用递推法。如何递推呢?我们假设有n个数分成m个部分,也可以看成切m个口。第一个切口切完后,我们就可以看成一个有n个数组成的长链。那末这第一刀就有n个切法,如下图所示。
我们就先对第一种切法进行研究,也就是把从1到n个数切m-1刀分成m个部分。首先我们想象第一部分可分为1个数字、2个数字、3个数字……(n-m)个数字。我们把其求和取模的结果分别存入数组的(n-m)个单元中。接着我们可以把第一、二部分合并考虑了,我们可以认为只有(n-m+1)个数字分成两个部分和(n-m)个数字分成两个部分……和2个数字分成两个部分的(n-m)种情况。见下图所示,两个部分寻找最大值过程。
我们再把每种情况中的最大值和最小值找出,分别存入d和x两个数组中。再接着我们可以把第一、二、三部分合并考虑了,我们可以认为只有(n-m+2)个数字分成三个部分和(n-m+1)个数字分成三个部分……和3个数字分成三个部分的(n-m)种情况。我们再把每种情况中的第三部分,分别于两个部分的最大值和最小值相乘就可以找到三个部分的最大值和最小值。如下图所示,三个部分寻找最大值过程。
如此进行下去,我们就可以把从1到n个数切m-1刀分成m个部分的最大值和最小值求出来。如此往复,我们就可以解出这道题了。
下面就是我所编的参考程序:
Var
a,b:Array[1..100]Of integer;
d,x:Array[1..50]Of longint;
m,n,l,i,j:Integer;
mk,sk:longint;
Procedure Work;
Var
i,j,s,k,k1:Integer;
da,xiao:longint;
Begin
for i:=1 to l do
begin
s:=0;
for j:=1 to l-i+1 do
begin
s:=s+b[m+j+i-2];
end;
d[i]:=s mod 10;
if d[i]0 then d[i]:=d[i]+10;
end;
x:=d;
for i:=m-1 downto 1 do
begin
for j:=1 to l do
begin
da:=0;xiao:
for k:=j to l do
begin
s:=0;
for k1:=j to k do
s:=s+b[i+k1-1];
s:=s mod 10;
if s0 then s:=s+10;
if das*d[k] then da:=s*d[k];
if xiaos*x[k] then xiao:=s*x[k];
end;
d[j]:=da;x[j]:=xiao;
文档评论(0)