Problem:
Problem F: Cleaning Robot

Here, we want to solve path planning for a mobile robot cleaning a
rectangular room floor with furniture.

Consider the room floor paved with square tiles whose size fits
the cleaning robot (1 × 1).
There are 'clean tiles' and 'dirty tiles', and the robot can change
a 'dirty tile' to a 'clean tile' by visiting the tile.
Also there may be some obstacles (furniture) whose size fits a
tile in the room. If there is an obstacle on a tile, the robot cannot visit
it.
The robot moves to an adjacent tile with one move.
The tile onto which the robot moves must be one of four tiles
(i.e., east, west, north or south) adjacent to the tile where the
robot is present. The robot may visit a tile twice or more.

Your task is to write a program which computes the minimum number of
moves for the robot to change all 'dirty tiles' to 'clean tiles',
if ever possible.

Input

The input consists of multiple maps, each representing the size
and arrangement of the room. A map is given in the following format.

w h

c11 c12 c13 ... c1w

c21 c22 c23 ... c2w

...

ch1 ch2 ch3 ... chw

The integers w and h are the lengths of the two sides
of the floor of the room in terms of widths of floor tiles. w and h
are less than or equal to 20. The character cyx represents
what is initially on the tile with coordinates (x, y) as follows.

'.' : a clean tile

'*' : a dirty tile

'x' : a piece of furniture (obstacle)

'o' : the robot (initial position)

In the map the number of 'dirty tiles' does not exceed 10.
There is only one 'robot'.

The end of the input is indicated by a line containing two zeros.

Output

For each map, your program should output a line containing the minimum
number of moves. If the map includes 'dirty tiles' which the robot cannot reach,
your program should output -1.

Sample Input

7 5
.......
.o...*.
.......
.*...*.
.......
15 13
.......x.......
...o...x....*..
.......x.......
.......x.......
.......x.......
...............
xxxxx.....xxxxx
...............
.......x.......
.......x.......
.......x.......
..*....x....*..
.......x.......
10 10
..........
..o.......
..........
..........
..........
.....xxxxx
.....x....
.....x.*..
.....x....
.....x....
0 0

Output for the Sample Input

8
49
-1

Solution in Ruby (judge verdict: Accepted)

class Heap
	require 'forwardable'
	extend Forwardable

	def initialize
		@array = []
		@index = {}
	end

	def add(obj, key)
		@array << [obj, key]
		@index[obj] = @array.size - 1
		lift_up(@array.size - 1)
	end

	def swap(i, j)
		u = @array[i]
		v = @array[j]
		@index[u[0]], @index[v[0]] = j, i
		@array[i], @array[j] = v, u
	end

	def lift_up(i)
		return if i == 0
		j = (i - 1) / 2
		if @array[i][1] < @array[j][1]
			swap(i, j)
			lift_up(j)
		end
	end

	def del_min
		raise "heap is empty!" if empty?
		min = @array[0]
		if size > 1
			swap(0, @array.size-1)
			@array.pop
			lift_down(0)
		else
			@array.pop
		end
		@index.delete(min[0])
		min
	end

	def inc_key(obj, diff)
		i = @index[obj]
		@array[i][1] += diff
		lift_down(i)
	end

	def dec_key(obj, diff)
		i = @index[obj]
		@array[i][1] -= diff
		lift_up(i)
	end

	def update_key(obj, new_key)
		i = @index[obj]
		return unless i
		return if new_key >= @array[i][1]
		@array[i][1] = new_key
		lift_up(i)
	end

	def min_obj
		@array[0][0]
	end

	def min_key
		@array[0][1]
	end

	def lift_down(i)
		j = 2 * i + 1
		k = j + 1
		if k >= size
			return if j >= size
			if @array[i][1] > @array[j][1]
				swap(i, j)
				lift_down(j)
			end
		else
			l = (@array[j][1] < @array[k][1] ? j : k)
			if @array[i][1] > @array[l][1]
				swap(i, l)
				lift_down(l)
			end
		end
	end

	def_delegators :@array, :empty?, :size
end

module Graphical
	require 'set'

	def reachable_from(s, max_depth = nil)
		reached = Set[s]
		queue = [s]
		depth = 0
		loop {
			break if max_depth && depth >= max_depth
			next_queue = []
			until queue.empty?
				u = queue.shift
				each_to_node_of(u){|v|
					next if reached.include?(v)
					reached << v
					next_queue << v
				}
			end
			break if next_queue.empty?
			queue = next_queue
			depth += 1
		}
		return reached
	end

	def dijkstra(start, setting = {})
		raise "invalid setting" if setting.class != Hash
		raise "invalid setting" if setting.keys - [:goal, :multi_source, :multi_sink, :max_dist] != []
		
		start = Set[start] if !setting[:multi_source]
		goal = setting[:goal]
		goal = Set[goal] if goal && !setting[:multi_sink]
		max_dist = setting[:max_dist]

		h = Heap.new
		reached = Set.new
		start.each{|v|
			h.add(v, 0)
			reached << v
		}

		dist = {}
		until h.empty?
			u, key = h.del_min
			return key if setting[:goal] && goal.include?(u)
			break if max_dist && key > max_dist
			dist[u] = key
			each_to_node_of(u){|v|
				d = dist[u] + edge_length(u, v)
				if reached.include?(v)
					h.update_key(v, d)
				else
					h.add(v, d)
					reached << v
				end
			}
		end
		goal ? nil : dist
	end

	def bidir_dijkstra(s, t)
		f_dist = {}
		b_dist = {}

		f_heap = Heap.new
		b_heap = Heap.new

		f_heap.add(s, 0)
		b_heap.add(t, 0)

		f_reached = Set[s]
		b_reached = Set[t]

		f_current_dist = b_current_dist = 0
		best = Float::INFINITY

		loop {
			if !f_heap.empty?
				u, key = f_heap.del_min
				f_dist[u] = key
				f_current_dist = key
				each_to_node_of(u){|v|
					d = f_dist[u] + edge_length(u, v)
					if b_dist[v]
						path_len = d + b_dist[v]
						best = path_len if path_len < best
					end
					if f_reached.include?(v)
						f_heap.update_key(v, d)
					else
						f_heap.add(v, d)
						f_reached << v
					end
				}
			end

			if !b_heap.empty?
				u, key = b_heap.del_min
				b_dist[u] = key
				b_current_dist = key
				each_from_node_of(u){|v|
					d = b_dist[u] + edge_length(v, u)
					if f_dist[v]
						path_len = d + f_dist[v]
						best = path_len if path_len < best
					end
					if b_reached.include?(v)
						b_heap.update_key(v, d)
					else
						b_heap.add(v, d)
						b_reached << v
					end
				}
			end

			return best if f_current_dist + b_current_dist >= best
			return nil if f_heap.empty? && b_heap.empty?
		}
	end
end

loop {
	w, h = gets.split.map &:to_i
	break if w == 0
	a = (1..h).map{ gets.chomp.split("") }
	start = nil
	targets = []
	(0..h-1).each{|i|
		(0..w-1).each{|j|
			start = [i, j] if a[i][j] == ?o
			targets << [i, j] if a[i][j] == ?*
		}
	}
	a.extend Graphical
	def a.each_to_node_of(node)
		y, x = node
		[[1,0],[-1,0],[0,-1],[0,1]].each{|dy, dx|
			u, v = x+dx, y+dy
			yield [v, u] if (0..self.size-1) === v && (0..self[0].size-1) === u && self[v][u] != ?x
		}
	end
	def a.edge_length(u, v)
		1
	end

	d = a.dijkstra(start)
	init_dist = (0..targets.size-1).map{|i| d[targets[i]]}
	if init_dist.include?(nil)
		puts -1
		next
	end

	dist = (0..targets.size-1).map{|i|
		d = a.dijkstra(targets[i])
		(0..targets.size-1).map{|j|
			d[targets[j]]
		}
	}

	best = Float::INFINITY
	stack = (0..targets.size-1).map{|i|
		[init_dist[i], i, (0..targets.size-1).to_a - [i]]
	}
	until stack.empty?
		d, i, rest = stack.pop
		if rest == []
			best = d if d < best
			next
		end
		next if d >= best
		rest.each{|j|
			stack << [d+dist[i][j], j, rest-[j]]
		}
	end
	p best

}