May 23, 2011
May 23, 2011
N/A Views
MD
warning
この記事は2年以上前に更新されたものです。情報が古くなっている可能性があります。

ウォームアップ問題

まずはウォームアップ問題を簡単に書く。

ケーキが2つあって、Aさんはケーキを好きな大きさで2つに切る。Bさんは切られたケーキのどっちかを先に選べる権利を1個目のケーキで使うか2個目のケーキで使うかの選択権がある。1個目のケーキを先に選んだ場合、2個目は後に選ばないといけない。Aさんは1個目の選択が終わった後に2個目のケーキを切る。
Aさん、Bさんともに自分ができるだけ大きいケーキを食べたいと思っている。

Aさんが食べるケーキを最大にするにはどういう戦略をとればいいか。そのときAさんが食べることができるケーキは何個か?

【解答】

1個目のケーキをf1-fに切り分ける。ここでfは大きい部分で、1/2 <= f <= 1を満たす(f=1といのはもう片方が無視できるくらい小さく切った場合)。

先にAさんが選ぶ場合、大きい方を選ぶのでfを取ることになる。2個目のケーキではBさんが大きい方をとるので、Bさんの取り分が最少になるように1/2できる。Aさんの食べるケーキをp個とすると、

p = f + 1/2 … ①

となる。


先にBさんが選ぶ場合、小さい方が残るので1-fを取ることになる。2個目はケーキでAさんは大きい方を取れるのでできるだけ大きく切る。Bさんの分は無視できるほど小さくなる。このときのAさんのケーキは

p = (1-f) + 1 = 2 - f … ②

となる。

①と②が同じ場合、Bさんがどっちを選んでもAさんは最大個のケーキを食べることができる。

つまり、f = 3/4で切ると、p = 5/4個食べることができる。

本題

では本題。

ウォームアップ問題同様に

  • ケーキが3個になった場合
  • ケーキが7個になった場合

どうすれば良いか?ついでにAさんはBさんよりどのくらい多く食べることができるか。

ここでAさんが先に選べる権利は1回だけで、残りはBさんが先に選べるとする。

【makingの解】

ケーキ3個の場合、同じようにf1-fに切り分ける。

最初にAさんが選ぶ場合、残り2個はBさんが先に選ぶのでずっと半分に切る。

最初にBさんが選ぶ場合、残り2個の状況はウォームアップ問題と同じになるのでf'=3/4で2個目を切ればのこり5/4個ゲットできる。

ということで

p = f + 1/2 + 1/2 = (1-f) + 5/4

を解けばOK。

最初に
f = 5/8できれば、p = 13/8個食べることができる。


あとは帰納的に解ける。

n個のケーキ

最初にAさんが選ぶ場合、残り(n-1)個はBさんが先に選ぶのでずっと半分に切る。

最初にBさんが選ぶ場合、残り(n-1)個の状況はケーキが(n-1)個のときと同じになる。

ケーキがn個のときのAさんの食べることができる最大の個数をp(n)とすると

p(n) = f + (n-1)*1/2 = (1-f) + p(n-1)

p(2) = 5/4

を解けば良い。

p(n) = (n+1)*1/4 + p(n-1)*1/2

f = (3-n)*1/4 + p(n-1)*1/2

AさんがBさんより多く食べることができる個数をm(n)とすると

m(n) = p(n) - (n - p(n)) = 2*p(n) - n

Clojureで解いてみる(分数が使えるので)

;; n < 2の場合は考えない。。
(defn p [n]
  (if (> n 2)
    (+ (/ (+ n 1) 4) (/ (p (- n 1)) 2))
    5/4))

;; 何度も使うのでメモ化
(def p (memoize p))

(defn f [n] (+ (/ (- 3 n) 4) (/ (p n) 2)))

;; 表示
(doseq [i (range 2 8)]
  (let [f (f i) p (p i)]
    (printf "n=%d,f=%6s,p=%7s,m=%4s%n" i f p (- (* 2 p) i))))

実行結果

n=2,f=   3/4,p=    5/4,m= 1/2
n=3,f=   5/8,p=   13/8,m= 1/4
n=4,f=  9/16,p=  33/16,m= 1/8
n=5,f= 17/32,p=  81/32,m=1/16
n=6,f= 33/64,p= 193/64,m=1/32
n=7,f=65/128,p=449/128,m=1/64

こんな感じ。高校数学みたいっすな。


面白かったらぽちって↓

プログラマのための論理パズル 難題を突破する論理思考トレーニング

Found a mistake? Update the entry.
Share this article: