User:Jeff/The Great Wall Game

Analysis
The input restrictions state that there can be at most 15 stones on a 15 x 15 board, which means a maximum of 32 possible configurations for the wall (15 rows, 15 columns, and 2 diagonals). This is a small enough number to attempt to reach each ending configuration, and return the smallest number of optimal moves found.

To solve this problem efficiently, we must make the following assumption: the shortest number of moves needed to get a peg from square a to square b is always equal to the Manhattan distance between points a and b, regardless of the positions of other stones on the board. (Manhattan distance is calculated by adding the absolute values of the differences between the x- and y-coordinates.) This assumption is true because the stones are all uniform; if one stone is in the way of another stone's shortest path to its destination, the second stone can move to that destination instead while the first stone takes the second one's place.

Therefore, the problem can be reduced to matching each stone from the input to its destination position in the final wall. Since the order in which the stones move doesn't matter, there are n! possible matchings. By using memoization, we can reduce the runtime to O(2n) calculations. This gives us a total runtime of O(n 2n), which is only on the order of one million in the worst case.

Using memoization for this problem
Given an array stones[0..n-1] and an array wall[0..n-1], we need to find the best matching between the elements in the arrays. We can write this function recursively by assuming that elements 0..x-1 in stones have already been matched. The function finds the best placement of stones[x] in the positions still available in wall through brute force, and recurses to match the remainder of the stones.

int bestMatch(vector &mem, int n, vector &stones,    vector &wall, int x, int wallMask) { if (mem[wallMask] != -1) return mem[wallMask]; if (x == n) return mem[wallMask] = 0; int ans(INF); for (int i(0); i < n; ++i) { if (wallMask & (1<<i)) continue; ans <?= dist(stones[x], wall[i]) + bestMatch(mem, n, stones, wall, x+1, (wallMask|(1<<i))); }  return ans; }