简单来说就是一个僵尸,初始等级为1,每过一个月提升1级,升级到2级之后就可以感染下一个人,将其变成1个1级的僵尸。(我不喜欢兔子的那个例子,因为我总是在纠结一个公兔和多个母兔子的问题)。
然后用递归来计算上面的问题就是:
function getNumber($month){
if($month==1){
return [1=>1,2=>0];
}
$lastMonth=getNumber($month-1);
return [1=>$lastMonth[2],2=>($lastMonth[2]+$lastMonth[1])];
}
$result=getNumber(6);
print_r($result);
/**
Array
(
[1] => 3
[2] => 5
)
**/
这个资料很多了,我是参考了B站的这个视频。
这里仅仅计算完成汉诺塔需要多少步,并不涉及其中的具体步骤:
<?php
class Town{
public function totoalStepsNumber($dishNumber){
if($dishNumber==1){
return 1;
}
return 1+2*$this->totoalStepsNumber($dishNumber-1);
}
}
$town=new Town();
print $town->totoalStepsNumber(4);
这里的思路很简单,就像宋丹丹和赵本山的那个小品一样,把大象关进冰箱需要几步,3步:打开冰箱门,把大象放进冰箱,关上冰箱门。
这里是同样的意义,无论中间的具体操作是什么,移动第i个汉诺塔的盘子,都需要先将前面i-1
个盘子移动到另一个盘子上,然后移动这第i个汉诺塔盘子,然后再将前面第i-1
个盘子移动到这个盘子上。
故名思义,就是在长度为n的字符串中,所有不包含连续两个0的字符串总量有多少?
这里我看错书上的意思,结果写成了获取所有的可能值的代码,但是结合这个看,可以更好理解总量的部分:
<?php
function withoutDoubleZero($length){
if($length==2){
return ['01','11','10'];
}
$lastword=withoutDoubleZero($length-1);
$returnData=[];
foreach($lastword as $word){
if(substr($word,-1,1)=='0'){
$returnData[]=$word."1";
}else{
$returnData[]=$word."0";
$returnData[]=$word."1";
}
}
return $returnData;
}
print_r(withoutDoubleZero(5));
或者我换成下面的图可以更容易理解:
在0的后面只能跟1,在1的后面可以随便跟0和1,都不会违反出现连续两个0的的情况。跟最开始的斐波那契数列的情况是一样的。
那个参考视频讲的真的很好,如果可以,建议直接去看视频。
这里首先定义一下相容的概念:讲座i的开始时间大于等于讲座k的结束时间,那么就可以说这两个讲座是相容的,在上面的例子中,讲座1和讲座2是不相容的,讲座3和讲座1是相容的。
再来就是p(j)
的定义,其表示为对于讲座j
来说接近的相容讲座,比如对于讲座7来说,讲座1,2,3,4都相容,但是讲座3最接近,所以p(7)=4
。
- p(1)=0
- p(2)=0
- p(3)=1
- p(4)=0
- p(5)=0
- p(6)=2
- p(7)=4
接下来加入每场讲座能参与的人员数:
接下来加入一个函数:opt(n)
,它代表按照时间往前排序时,安排第n场讲座的最优解。
现在从讲座7开始考虑,对于讲座7有2种选择,安不安排讲座7:
-
安排讲座7:总人数为
opt(4)+10
-
不安排讲座7时:总人数为
opt(6)
这里解释两个值,为什么安排讲座时,总人数是opt(4)+10
,opt(4)
是因为如果一定要安排讲座7,则不可能安排讲座5,6,因为5,6和7不兼容,所以只能是和7兼容的最大值,即opt(p(7))
,再加上讲座7所能容纳的参与人数10。
再来就是不安排讲座7时,那么就先假设总人数最优解为opt(6)
,这里不用纠结为什么是opt(6)
,因为opt(6)
也不一定是我们的最终结果,这里只是将其作为一个中间值而已。
按照上面的思路,我们继续考虑,不安排讲座7时,opt(6)
的值,这个时候又有2个选择,是否安排讲座6:
- 安排讲座6:总人数为
opt(2)+20
- 不安排讲座6:总人数为
opt(5)
将上面的结果制作成树状图就是下面的形式:
从最上面开始看起,如果opt(7)
可以延生出两条线,opt(4)+10
和opt(6)
,分表代表安排讲座7和不安排讲座7,接下来针对opt(4)
,也有两种选择,安排讲座4和不安排讲座4,安排讲座4则能增加30人,不安排讲座4,则计算opt(3)
。以此类推直到opt(1)
,如果安排讲座1,则人数为10人,不安排讲座1,则0人,所以我们可以知道opt(1)=10
,然后往上走到opt(2)
,如果安排讲座2,则人数为20人,否则人数为opt(1)=10
人,所以opt(2)=20
,以此类推直到回到最上面的opt(4)+10=40
。
接下来在opt(6)
那一侧,因为之前就计算过opt(2),opt(4)
的值,所以不会再去计算一次,按照左侧的计算逻辑,得出最优解为只安排讲座5,人数为100人。
<?php
$p=[
1=>0,
2=>0,
3=>1,
4=>0,
5=>0,
6=>2,
7=>4
];
$sites=[
1=>10,
2=>20,
3=>20,
4=>30,
5=>100,
6=>20,
7=>10
];
$cache=[];
function opt($n){
global $sites,$p,$cache;
if(isset($cache[$n])){
return $cache[$n];
}
if($n<=0){
return 0;
}
$cache[$n]=max(opt($n-1),opt($p[$n])+$sites[$n]);
return $cache[$n];
}
print opt(7);
print PHP_EOL;
print_r($cache);
输出结果:
100
Array
(
[1] => 10
[2] => 20
[3] => 30
[4] => 30
[5] => 100
[6] => 100
[7] => 100
)