初次Python 暴力解益智遊戲 ( 二 )
因為不可能讓程式自己獨立解出答案,改成可以支持各種操作的方式輔助縮減答案範圍,再用人腦解決。
第二次寫就好很多了,語法也比較熟悉。
這個版本支持輸入 $表示空的格子,也能指定遞迴深度,還有事先寫好哪些字是禁用的。利用的剪枝還是比較基礎,對於需要的長度的 multiset和超過最大長度就馬上返回。
這次學到的python比較坑的一點是,如果單純對兩個字串寫 T[ i ] = g[ i ],似乎只會參照,也就是修改 T[ i ] 這個字串中的任何字都會直接影響 g[ i ]。還有 python中的字串是不能直接改變裡面的字元的,這點印象中跟 java是一樣的。
import enchant from collections import Counter d = enchant.Dict( "en_US" ) f = open( 'banned', 'r' ) banned = set() for line in f: banned.add( line[ : -1 ] ) MAXLEN = 0 dx = [ 0, 1, 0, -1, 1, -1, 1, -1 ] dy = [ 1, 0, -1, 0, -1, 1, 1, -1 ] def outOfRange( x, y ): return x < 0 or x >= n or y < 0 or y >= m def drop( g, path ): T = [ "" for i in xrange( n ) ] for i in xrange( n ): T[ i ] = g[ i ][ : ] for ( i, j ) in path: T[ i ] = T[ i ][ 0 : j ] + '$' + T[ i ][ j + 1 : ] for _i in xrange( n ): for j in xrange( m ): i = n - _i - 1 if T[ i ][ j ] != '$': continue k = i while T[ k ][ j ] == '$': k -= 1 if k < 0: break if k >= 0: T[ i ] = T[ i ][ 0 : j ] + T[ k ][ j ] + T[ i ][ j + 1 : ] T[ k ] = T[ k ][ 0 : j ] + '$' + T[ k ][ j + 1 : ] """for i in xrange( n ): for j in xrange( m ): print T[ i ][ j ], print ''""" return T def rsolve( g, slist, depth ): global ans, vis if depth == dpt: if determine: for i in xrange( MAXLEN + 1 ): if qlen[ i ] > 0: return print slist # ans.append( slist ) return for i in xrange( n ): for j in xrange( m ): if g[ i ][ j ] != '$': for _i in xrange( n ): for _j in xrange( m ): vis[ depth + 1 ][ _i ][ _j ] = 0 dfs( g, i, j, [], [], slist, depth + 1 ) def dfs( g, sx, sy, vc, path, slist, depth ): if len( vc ) > MAXLEN: return global vis, ans vis[ depth ][ sx ][ sy ] = 1 vc.append( g[ sx ][ sy ] ) path.append( ( sx, sy ) ) s = ''.join( vc ) if qlen[ len( s ) ] > 0 and d.check( s ) and s not in banned: qlen[ len( s ) ] -= 1 T = drop( g, path ) slist.append( s ) rsolve( T, slist, depth ) slist.pop() qlen[ len( s ) ] += 1 for di in xrange( 8 ): nx = sx + dx[ di ] ny = sy + dy[ di ] if outOfRange( nx, ny ): continue if g[ sx ][ sy ] == '$': continue if vis[ depth ][ nx ][ ny ]: continue dfs( g, nx, ny, vc, path, slist, depth ) path.pop() vc.pop() vis[ depth ][ sx ][ sy ] = 0 def printAns(): if len( ans ) == 0: print "Answer not found, maybe some letter must be capitalized." else: for s in ans: print s def solve(): rsolve( G, [], 0 ) # printAns() G = [ "" for i in xrange( 8 ) ] vis = [ [ [ 0 for i in xrange( 8 ) ] for j in xrange( 8 ) ] for depth in xrange( 30 ) ] ans = [] qlen = Counter() n = int( input( "n = " ) ) m = int( input( "m = " ) ) q = int( input( "q = " ) ) for i in xrange( q ): v = ( int( input( "len %d : " % ( i + 1 ) ) ) ) qlen[ v ] += 1 MAXLEN = max( MAXLEN, v ) determine = 0 dpt = int( input( "Try depth ( add 2 extra 0s to imply determination ) = " ) ) if dpt >= 100: dpt /= 100 determine = 1 for i in xrange( n ): G[ i ] = raw_input( "Row %d : " % ( i + 1 ) ) solve()