見出し画像

「プログラマ脳を鍛える数学パズル」を解いてみる初級編#5【アルゴリズム学習】

概要

翔泳社から出版されている「プログラマ脳を鍛える数学パズル」のプログラミング問題をC++で解きます。
この本ではRuby,JavaScript,Cでの解答はありますが、C++は載っていないため練習として解いてみようと思います。
記事、コード共にまだまだな部分も多いので、何かお気づきの点があれば、コメントお願いいたします。

ぜひ、いいねと思ったらスキお願いいたします!!!
見出し画像は京都の四条の「ホルモン千葉」での写真です。すごくおいしかったので、おすすめです。ただし、ニンニクの量がすごいです…

【今回のキーワード】
・動的計画法
・メモ化
・深さ優先探索

問題1

Q22:絡まない糸電話

q22問題文

解答1

ソースコード
これはRubyのコードと同じ感じでいけました

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(),(x).end()
#define repi(i,a,n) for(int i = (int)a; i < (int)(n); i++)
#define ll long long

int main(void){
   int n=16;
   std::vector<int> pair(n/2+1);
   
   pair[0]=1;
   
   //交差しない=偶数人ずつのエリアに分けてその中で糸電話をする
   repi(i,1,n/2+1){
       pair[i]=0;
       rep(j,i){
           pair[i]+=pair[j]*pair[i-j-1];
       }
   }
   std::cout << pair[n/2] <<"通り"<< std::endl;
}

実行結果

画像4

問題2

Q23:ブラックジャックで大儲け

q23問題文

解答2

ソースコード
memo配列に入っているかの判定を-1で初期化することで実装しました

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(),(x).end()
#define repi(i,a,n) for(int i = (int)a; i < (int)(n); i++)
#define ll long long

const int c=10;
const int d=24;
ll int memo[c+d+1][d+1];


//深さ優先探索で何通りあるか求める
//coinは残りのコイン枚数,depthは残りのゲーム可能回数を示す
ll int blackjack(int coin,int depth){
   if(memo[coin][depth] != -1){
       return memo[coin][depth];
   }
   //コインがゼロの時はゲーム"できない"ので0を返す
   if(coin==0){
       return 0;
   }
   //回数がゼロの時は持っているコイン枚数でゲーム"終了"のため1を返す
   if(depth==0){
       return 1;
   }
   ll int win=blackjack(coin+1,depth-1);//勝ったときはコインの枚数を増やして再帰
   ll int lose=blackjack(coin-1,depth-1);//負けたときはコインの枚数を減らして再帰
   memo[coin][depth]=win+lose;
   return memo[coin][depth];
}

int main(void){
   //初期化
   rep(i,c+d+1){
       rep(j,d+1){
           memo[i][j]=-1;
       }        
   }
   std::cout << blackjack(c,d) <<"通り"<< std::endl;
}

実行結果

画像3

今回の学び

・メモ化、動的計画法、深さ優先探索は頻出パターンなので、問題文を早く理解して時間を意識して実装する
・問題の状況を具体的に考えて、正確に実装する。具体的には、q23はコインが0枚の時と、ゲーム回数が0回の時とでそこで計算が終了する点は同じだが、結果が異なることに注意する。

参考文献

「プログラマを鍛える数学パズル」著:増井敏克



この記事が気に入ったらサポートをしてみませんか?