トップページに戻る
次のPHPのサンプルへ
前のPHPのサンプルへ
Q21 本の読み方は何通り?
PHPのソース
<?php
Solve(100, 3); // 834
Solve(180,14); //140615467
class JyoutaiDef
{
public $RestPageCnt;
public $MaxPage;
}
function Solve($pTotalPageCnt , $pDayCnt)
{
//場合の数[ハッシュ値]なDP表
$wkJyoutai = new JyoutaiDef();
$wkJyoutai->RestPageCnt = $pTotalPageCnt;
$wkJyoutai->MaxPage = $pTotalPageCnt;
$wkHash = GetHash($wkJyoutai);
$PrevDP = array($wkHash => 1);
$Answer = 0;
for($I = 1 ; $I <= $pDayCnt ; $I++){
$CurrDP = array();
foreach($PrevDP as $EachHash => $EachVal){
$wkJyoutai = DeriveJyoutai($EachHash);
for($J = 1 ; $J <= $wkJyoutai->MaxPage ; $J++){
$NewJyoutai = new JyoutaiDef();
$NewJyoutai->RestPageCnt = $wkJyoutai->RestPageCnt - $J;
if($NewJyoutai->RestPageCnt < 0) break;
$NewJyoutai->MaxPage = $J - 1;
$Hash = GetHash($NewJyoutai);
if(array_key_exists($Hash,$CurrDP))
$CurrDP[$Hash] += $EachVal;
else $CurrDP[$Hash] = $EachVal;
}
}
foreach($CurrDP as $EachHash => $EachVal){
$wkJyoutai = DeriveJyoutai($EachHash);
if($wkJyoutai->RestPageCnt == 0)
$Answer += $EachVal;
}
$PrevDP = $CurrDP;
}
printf('%dページを%d日以内で読むのは、%d通り' , $pTotalPageCnt , $pDayCnt , $Answer);
echo PHP_EOL;
}
function GetHash(JyoutaiDef $pJyoutai)
{
$WillReturn = 0;
$WillReturn += $pJyoutai->RestPageCnt * 1000;
$WillReturn += $pJyoutai->MaxPage;
return $WillReturn;
}
function DeriveJyoutai($pHash)
{
$WillReturn = new JyoutaiDef();
$WkMod = $pHash % 1000;
$WillReturn->RestPageCnt = ($pHash - $WkMod) / 1000;
$WillReturn->MaxPage = $WkMod;
return $WillReturn;
}
実行結果
100ページを3日以内で読むのは、834通り
180ページを14日以内で読むのは、140615467通り
解説
場合の数[状態のHash値]
を更新する動的計画法で解いてます。