【LeetCode 773】滑动谜题

15 篇文章 0 订阅
/*
难度:困难
在一个2x3的板上有5块砖瓦,用数字1~5来表示,以及一块空缺用0表示。
一次移动定义为选择0与一个相邻的数字进行交换。
最终当板上的结果是 [[1,2,3], [4,5,0]]时,谜板被揭开。
给出一个初始状态,返回最少可以通过多少次移动揭开谜板,如果解不开,则返回-1
*/ 
class Node773 {
	var code: Int	
	var connected = [Int]() //与本节点有连线的其他节点
	init(code: Int) {
		self.code = code
	}
	
	static let nodesMap: [Int:Node773] = {
		var tempMap = [Int:Node773]()
		for a in 0..<6 {
			let sa = a * 100000
			for b in 0..<6 {
				if b == a {
					continue
				}
				let sb = b * 10000
				for c in 0..<6 {
					if c == a || c == b {
						continue
					}
					let sc = c * 1000
					for d in 0..<6 {
						if d == c || d == b || c == a {
							continue
						}
						let sd = d * 100
						for e in 0..<6 {
							if e == d || e == c || e == b || e == a {
								continue
							}
							let se = e * 10
							for f in 0..<6 {
								if f == e || f == d || f == c || f == b || f == a {
									continue
								}
								let code = sa + sb + sc + sd + se + f
								let node = Node773(code: code)
								
								//相连的节点
								if a == 0 {
									node.connected.append(code - sb + b*100000)
									node.connected.append(code - sd + d*100000)
								} else if b == 0 {
									node.connected.append(code - sa + a*10000)
									node.connected.append(code - sc + c*10000)
									node.connected.append(code - se + e*10000) //1 和 4比四角要多一个
								} else if c == 0 {									
									node.connected.append(code - sb + b*1000)
									node.connected.append(code - f + f*1000)
								} else if d == 0 {
									node.connected.append(code - sa + a*100)
									node.connected.append(code - se + e*100)
								} else if e == 0 {
									node.connected.append(code - sd + d*10)
									node.connected.append(code - f + f*10)
									node.connected.append(code - sb + b*10) //1 和 4比四角要多一个
								} else if f == 0 {
									node.connected.append(code - sc + c)
									node.connected.append(code - se + e)
								}
								tempMap[code] = node
							}
						}
					}
				}
			}
		}
		return tempMap
	}()
}
extension Daily {
	static func test_leetcode773() {
//		let board = [[1,2,3], [4,0,5]]
//		let board = [[1,2,3], [5,4,0]]
//		let board = [[4,1,2],[5,0,3]]
		let board = [[3,2,4],[1,5,0]]
		let res = Daily.leetcode773(board)
		print("结果 \(res)")
	}
	
	static func leetcode773(_ board: [[Int]]) -> Int {
		let target = 123450
		let startCode = board[0][0]*100000 + board[0][1]*10000 + board[0][2]*1000 +
			board[1][0]*100 + board[1][1]*10 + board[1][2]
		
		let nodesMap = Node773.nodesMap
		let startNode: Node773! = nodesMap[startCode]
		if startNode == nil {
			return -1
		}
		
		var map = [Int:Int]()
		for item in nodesMap.keys {
			if item != startCode {
				map[item] = 1000
			}
			else {
				map[item] = 0
			}
		}
		var finished = [Int:Int]()
		var todo = [Int]()
		todo.append(contentsOf: startNode.connected)
		for item in startNode.connected {
			map[item] = 1
		}
		var idx = 0
		while todo.count > 0 && idx < todo.count {
			let pcode = todo[idx]
			if pcode == target {
				break
			}
			let pnode = nodesMap[pcode]!
			
			for item in pnode.connected {
				let done = finished[item] 
				if done == nil {				
					todo.append(item)
					finished[item] = 1
				}
				if map[item]! > map[pcode]! + 1 {
					map[item] = map[pcode]! + 1
				}
			}
			finished[pcode] = 2
			idx += 1
		}
		return map[target]! == 1000 ? -1 : map[target]!
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值