2. 2011/4/27 アルゴリズムとデータ構造 15 2
N クイーン問題
N×N のチェス盤に, N 個のクイーンの駒を置いて,それぞれが
他のクイーンの利き筋(縦,横,斜め)に当たらないようにす
る
N =8の例:正しい配置 間違った配置
3. 2011/4/27 アルゴリズムとデータ構造 15 3
N クイーン問題の力まかせ法による
解
サイズ n の N クイーン問題を解く
def n_queen(n):
A = array(n)
for i in range(n): A[i] = 0
while A != None:
if valid(A, n): return A
A = next(A, n)
return None
次候補となる盤面を返す
def next(A, n):
for i in range(n):
if A[i] == n-1:
A[i] = 0
else:
A[i] = A[i] + 1
return A
return None
盤面が有効かどうかチェック
def valid(A, n):
for i in range(n-1):
k = 1
for j in range(i+1, n):
if A[i] == A[j]:
return False
if (A[i] == A[j] + k
or A[j] == A[i] + k):
return False
k = k + 1
return True
5. 2011/4/27 アルゴリズムとデータ構造 15 5
N クイーン問題のバックトラック
解法
def n_queen(n):
B = board(n); backtrack(B, n, 0)
def board(n):
b = array(n);
for i in range(n):
b[i] = array(n);
for j in range(n):
b[i][j] = False
return b
def backtrack(B, n, level):
if level >= n: print(B); return
row = level
for col in range(n):
if check(B, row, col):
B[row][col] = True
backtrack(B, n, level + 1)
B[row][col] = False
6. 2011/4/27 アルゴリズムとデータ構造 15 6
N クイーン問題のバックトラック解
法 (2)
def check(B, row, col):
for i in range(len(B)):
if B[row][i] or B[i][col]:
return False
if row+i < n and col+i < n and B[row+i][col+i]:
return False
if row-i >= 0 and col+i < n and B[row-i][col+i]:
return False
if row+i < n and col-i >= 0 and B[row+i][col-i]:
return False
if row-i >= 0 and col-i >= 0 and B[row-i][col-i]:
return False
return True
8. 2011/4/27 アルゴリズムとデータ構造 15 8
解答例
def n_queen(n):
b = board(n); backtrack(b, n, 0)
def board(n):
b = record([‘rows’, ‘horizontal’,
‘major’, ‘minor’])
b.rows = array(n)
b.horizontal = array(n)
for i in range(n): b.horizontal[i] = True
b.major = array(2 * n – 1)
b.minor = array(2 * n – 1)
for i in range(2 * n – 1):
b.major[i] = b.minor[i] = True
return b
9. 2011/4/27 アルゴリズムとデータ構造 15 9
解答例(続き)
def backtrack(B, n, level):
if level >= n: print(B.rows); return
row = level
for col in range(n):
B.rows[row] = col
if (B.horizontal[col] and B.major[row+col]
and B.minor[row-col]):
B.horizontal[col] = False
B.major[row+col] = False
B.minor[row-col] = False
backtrack(B, n, level + 1)
B.rows[col] = None
B.horizontal[col] = True
B.major[row+col] = True
B.minor[row-col] = True
12. 2011/4/27 アルゴリズムとデータ構造 15 12
動的計画法の例
フィボナッチ数列:
再帰的定義にもとづくプログラム
def fib(n):
if n == 0 or n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
動的計画法を利用したプログラム
def fib(n):
n1 = n2 = result = 1
for i in range(1, n):
result = n1 + n2
n1 = n2
n2 = result
return result
FIB(4)
FIB(3) FIB(2)
FIB(2) FIB(1)
FIB(1) FIB(0)
FIB(1) FIB(0)
同じ計算を何
度も繰り返す
ため,非効率
的
13. 2011/4/27 アルゴリズムとデータ構造 15 13
Levenshtein Distance (編集距離)
2つの文字列がどれだけ異なっているか
2つの文字列を一致させるために必要な文字の挿
入,削除,置換操作の最小回数
”例: kitten” ”と sitting”
kitten ⇒ sitten sitt⇒ in sittin⇒ g
LD(“kitten”, ”sitting”) = 3
練習問題:次の文字列の編集距離はいくら
か?
apple と couple
14. 2011/4/27 アルゴリズムとデータ構造 15 14
DP を用いて編集距離を求める
アルゴリズムのポイ
ント
長さ 0 の文字列と長さ
n の文字列の LD は n
LD(s1,s2) は,以下のう
ちの最小のもの
置換: LD(s1-1,s2-1) + (if
s1.last = s2.last then 0
else 1)
挿入: LD(s1-1,s2) + 1
削除: LD(s1,s2-1) + 1
※ 文字列 s-1 は文字列 s から末尾の文字
を
削除したものとする
k i t t e n
0 1 2 3 4 5 6
s 1 1 2 3 4 5 6
i 2 2 1 2 3 4 5
t 3 3 2 1 2 3 4
t 4 4 3 2 1 2 3
i 5 5 4 3 2 2 3
n 6 6 5 4 3 3 2
g 7 7 6 5 4 4 3
15. 2011/4/27 アルゴリズムとデータ構造 15 15
LD を求めるコード例
def levenshtein_distance(s1, s2):
m = len(s1)
n = len(s2)
D = array2(m+1, n+1)
for i in range(m+1): D[i][0] = i
for j in range(n+1): D[0][j] = j
for i in range(1, m+1):
for j in range(1, n + 1)::
if s1[i-1] == s2[j-1]: cost = 0
else: cost = 1
D[i][j] = min(D[i-1][j]+1,
D[i][j-1]+1,
D[i-1][j-1]+cost)
return D[m][n]
17. 2011/4/27 アルゴリズムとデータ構造 15 17
動的計画法を用いた解法
入力:問題 P( ナップサックの大きさ w, 品物リスト items)
items[i].size は品物 i の大きさ, items[i].value は金額を表す
def knapsack(P):
cost = array(P.w)
best = array(P.w)
for i in range(P.w):
cost[i] = best[i] = 0
for i in range(len(P.items)):
for j in range(P.w):
if j >= P.items[i].size:
if cost[j] < cost[j-P.items[i].size]+P.items[i].value:
cost[j] = cost[j-P.items[i].size]+P.items[i].value
best[j] = i
return cost[P.w-1]
18. 2011/4/27 アルゴリズムとデータ構造 15 18
実行の様子
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
5 5 5 10 10 10 15 15 15 20 20 20 25 25 25 30 30 30 35
a a a a a a a a a a a a a a a a a a a
5 5 7 10 10 12 15 15 17 20 20 22 25 25 27 30 30 32 35
a a b a a b a a b a a b a a b a a b a
5 5 7 10 10 12 15 15 21 21 21 26 26 28 31 31 33 36 36
a a b a a b a a c c c c c c c c c c c
j
i
cost1[]
best1[]
cost2[]
best2[]
cost3[]
best3[]
品物 a b c
大き
さ
3 5 11
金額 5 7 21