- 論壇徽章:
- 0
|
前幾天看到hdu 1195:
Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbered from 1 to 9.
Each time, you can add or minus 1 to any digit. When add 1 to '9', the digit will change to be '1' and when minus 1 to '1', the digit will change to be '9'. You can also exchange the digit with its neighbor. Each action will take one step.
Now your task is to use minimal steps to open the lock.
Note: The leftmost digit is not the neighbor of the rightmost digit.
我用如下代碼解,其中用到了兩個假設(shè):
1. 對于給定操作步驟,操作順序可以打亂。(將各位編號,交換同時交換編號,增減操作綁定編號)
2. 對于可通過純交換實現(xiàn)的變化,則最少交換步驟等同于將源組合冒泡排序至目標組合。
calculate函數(shù)求解,參數(shù)為 源狀態(tài) 終狀態(tài),結(jié)果為 (最少步數(shù), _)- import Data.Maybe
- import Data.List
- steps4Exchange :: [ Int ] -> Int
- steps4Exchange dst =
- snd $ iterate swapPass (dst, 0) !! (length dst - 1)
- where swapPass ([ x ], i) = ([ x ], i)
- swapPass (x : y : zs, i)
- | x > y =
- let (xs, i') = swapPass (x : zs, i + 1) in
- (y : xs, i')
- | otherwise =
- let (xs, i') = swapPass (y : zs, i) in
- (x : xs, i')
- steps4Move :: [ Int ] -> [ Int ] -> Int
- steps4Move src dst =
- sum $ map (\(s, i) ->
- let d = dst !! i in
- min (abs (d - s)) (9 + s - d)
- ) $ zip src [ 0 .. ]
- calculate :: [ Int ] -> [ Int ] -> (Int, [ Int ])
- calculate src dst =
- let src' = zip src [ 0 .. ] in
- foldl1 (\(a, a') (b, b') ->
- if a > b then
- (b, b')
- else
- (a, a')
- ) $ map (\mid' ->
- let mid = fst $ unzip mid' in
- (steps4Exchange (snd $ unzip mid') + steps4Move mid dst, mid)
- ) $ permutations src'
復制代碼 |
|