@SuppressWarnings("unchecked")
  public int getMinimumMoves(String[] board) {
    PriorityQueue<Long> pq = new PriorityQueue<Long>();
    HashMap<Long, Integer> map = new HashMap<Long, Integer>();

    ArrayList<Integer> pieces = new ArrayList<Integer>();
    for (int i = 0; i < 5; i++) {
      for (int j = 0; j < 5; j++) {
        if (board[i].charAt(j) == '*') {
          pieces.add((i << 3) | j);
        }
      }
    }
    N = pieces.size();

    pq.add(pack(pieces));
    while (pq.size() > 0) {
      long a = pq.poll();
      long k = a & 0xFFFFFFFFL;
      int c = (int) (a >>> 32);

      if (map.containsKey(k)) continue;
      map.put(k, c);

      ArrayList<Integer> unpack = unpack(k);

      if (connected(unpack)) return c;

      for (int i = 0; i < N; i++) {
        int piece = unpack.get(i);
        int x = piece >>> 3;
        int y = piece & 0x7;

        for (int j = 0; j < dir.length; j++) {
          ArrayList<Integer> copy = (ArrayList<Integer>) unpack.clone();
          copy.remove(i);

          if (x + dir[j][0] < 0 || x + dir[j][0] >= 5 || y + dir[j][1] < 0 || y + dir[j][1] >= 5)
            continue;
          int newp = ((x + dir[j][0]) << 3) | (y + dir[j][1]);

          if (copy.contains(newp)) continue;
          copy.add(newp);

          long test = pack(copy);

          if (map.get(test) == null || map.get(test) > c + 1) {
            pq.add((((long) c + 1) << 32) | test);
          }
        }
      }
    }
    return -1;
  }
  private static int dijkstra(int s, int e, int[] cost, int[][] flow) {
    int[] best = new int[cost.length];
    Arrays.fill(best, -1);
    best[s] = cost[s];
    PriorityQueue<Node> pq = new PriorityQueue<Node>();
    pq.add(new Node(cost[s], s));
    while (pq.size() > 0) {
      Node n = pq.poll();

      if (n.at == e) return n.cost;
      if (n.cost < best[n.at]) continue;
      for (int i = 0; i < cost.length; i++) {
        if (flow[n.at][i] > 0) {
          int c = min(cost[i], n.cost);
          if (c > best[i]) {
            best[i] = c;
            pq.add(new Node(c, i));
          }
        }
      }
    }
    return 0;
  }