sample\algorithms\07_dp.hsp » Plain Format
;============================================================
; アルゴリズム 31〜35: 動的計画法 (DP)
; 31. 0/1 Knapsack
; 32. Unbounded Knapsack
; 33. Longest Increasing Subsequence (LIS) O(N log N)
; 34. Coin Change (最小枚数)
; 35. Edit Distance (operations trace 付)
;============================================================
#include "hsp3cl_net_64.as"
; ----- 31. 0/1 Knapsack -----
#module
#defcfunc knapsack_01 array _w, array _v, int _n, int _cap, \
local _i, local _j, local _alt
dim _dp, (_n + 1) * (_cap + 1)
repeat _n
_i = cnt + 1
repeat _cap + 1
_j = cnt
_dp(_i * (_cap + 1) + _j) = _dp((_i - 1) * (_cap + 1) + _j)
if _j >= _w(_i - 1) {
_alt = _dp((_i - 1) * (_cap + 1) + _j - _w(_i - 1)) + _v(_i - 1)
if _alt > _dp(_i * (_cap + 1) + _j) : _dp(_i * (_cap + 1) + _j) = _alt
}
loop
loop
return _dp(_n * (_cap + 1) + _cap)
#global
; ----- 32. Unbounded Knapsack -----
#module
#defcfunc knapsack_un array _w, array _v, int _n, int _cap, \
local _i, local _j, local _alt
dim _dp, _cap + 1
repeat _cap
_j = cnt + 1
repeat _n
_i = cnt
if _w(_i) <= _j {
_alt = _dp(_j - _w(_i)) + _v(_i)
if _alt > _dp(_j) : _dp(_j) = _alt
}
loop
loop
return _dp(_cap)
#global
; ----- 33. LIS (O(N log N), patience) -----
#module
#defcfunc lis array _a, int _n, \
local _i, local _lo, local _hi, local _mid, local _len
dim _tails, _n
_len = 0
repeat _n
_i = cnt
_lo = 0 : _hi = _len
repeat
if _lo >= _hi : break
_mid = (_lo + _hi) / 2
if _tails(_mid) < _a(_i) : _lo = _mid + 1 : else : _hi = _mid
loop
_tails(_lo) = _a(_i)
if _lo == _len : _len++
loop
return _len
#global
; ----- 34. Coin Change (最小枚数) -----
#module
#defcfunc coin_change array _coins, int _m, int _amt, \
local _i, local _j, local _INF, local _alt
_INF = 0x7FFFFFFF
dim _dp, _amt + 1
repeat _amt : _dp(cnt + 1) = _INF : loop
repeat _amt
_i = cnt + 1
repeat _m
_j = cnt
if _coins(_j) <= _i : if _dp(_i - _coins(_j)) != _INF {
_alt = _dp(_i - _coins(_j)) + 1
if _alt < _dp(_i) : _dp(_i) = _alt
}
loop
loop
if _dp(_amt) == _INF : return -1
return _dp(_amt)
#global
; ----- 35. Edit Distance + Trace -----
#module
#deffunc edit_distance_trace var _a, var _b, var _dst, var _ops, \
local _i, local _j, local _la, local _lb, local _a1, local _a2, local _a3, local _m, \
local _ci, local _cj
_la = strlen(_a) : _lb = strlen(_b)
dim _dp, (_la + 1) * (_lb + 1)
repeat _la + 1 : _dp(cnt * (_lb + 1)) = cnt : loop
repeat _lb + 1 : _dp(cnt) = cnt : loop
repeat _la
_i = cnt + 1
repeat _lb
_j = cnt + 1
_ci = peek(_a, _i - 1)
_cj = peek(_b, _j - 1)
if _ci == _cj {
_dp(_i * (_lb + 1) + _j) = _dp((_i - 1) * (_lb + 1) + _j - 1)
} else {
_a1 = _dp((_i - 1) * (_lb + 1) + _j) + 1
_a2 = _dp(_i * (_lb + 1) + _j - 1) + 1
_a3 = _dp((_i - 1) * (_lb + 1) + _j - 1) + 1
_m = _a1
if _a2 < _m : _m = _a2
if _a3 < _m : _m = _a3
_dp(_i * (_lb + 1) + _j) = _m
}
loop
loop
_dst = _dp(_la * (_lb + 1) + _lb)
sdim _ops, 512
_ops = ""
_i = _la : _j = _lb
repeat
if (_i <= 0) & (_j <= 0) : break
if (_i > 0) & (_j > 0) {
_ci = peek(_a, _i - 1) : _cj = peek(_b, _j - 1)
if _ci == _cj : _i-- : _j-- : continue
if _dp(_i * (_lb + 1) + _j) == _dp((_i - 1) * (_lb + 1) + _j - 1) + 1 {
_ops = strf("replace '%c'->'%c' at %d\n", _ci, _cj, _i - 1) + _ops
_i-- : _j-- : continue
}
}
if _i > 0 : if _dp(_i * (_lb + 1) + _j) == _dp((_i - 1) * (_lb + 1) + _j) + 1 {
_ci = peek(_a, _i - 1)
_ops = strf("delete '%c' at %d\n", _ci, _i - 1) + _ops
_i--
continue
}
_cj = peek(_b, _j - 1)
_ops = strf("insert '%c' at %d\n", _cj, _i) + _ops
_j--
loop
return
#global
; ===== デモ =====
mes "=== 0/1 Knapsack ==="
dim kw, 3 : kw = 2, 3, 4
dim kv, 3 : kv = 3, 4, 5
v01 = knapsack_01(kw, kv, 3, 5)
mes strf("items=(w:2,v:3),(w:3,v:4),(w:4,v:5), cap=5 => max=%d", v01)
mes strf("Unbounded: max=%d", knapsack_un(kw, kv, 3, 5))
mes ""
mes "=== LIS ==="
dim la_arr, 8 : la_arr = 10, 22, 9, 33, 21, 50, 41, 60
mes strf("LIS of [10,22,9,33,21,50,41,60] = %d (期待: 5)", lis(la_arr, 8))
mes ""
mes "=== Coin Change ==="
dim c, 3 : c = 1, 3, 4
mes strf("min coins for 6 (from {1,3,4}) = %d", coin_change(c, 3, 6))
mes strf("min coins for 11 = %d", coin_change(c, 3, 11))
mes ""
mes "=== Edit Distance with trace ==="
s1 = "kitten" : s2 = "sitting"
edit_distance_trace s1, s2, dst, ops
mes strf("Distance = %d", dst)
mes "Operations:"
mes ops
end 0