URL: http://www.topcoder.com/stat?c=problem_statement&pm=10412
This problem asks us to determine the minimum number of simple planar graphs we need to exact use of N gold coins. Each planar graph has an associated cost function based on the number of vertices and edges the graph has, more specifically: cost = (number of vertices)^3 + (number of edges)^2. We should immediately see a knapsack-like algorithm which strongly suggests using dynamic programming. The main problem lies with determining what number of vertices and edges constitutes a valid simple planar graph.
Luckily there is a simple theorem which we can use as an upper bound calculation to determine whether a pairing of (#V,#E) is a valid pair. For graphs that has at least 3 vertices: if e > 3v - 6 then this will imply nonplanarity. Hence, we can deduce that all e <= 3v - 6 has a simple planar graph representation. For graphs that has less than 3 vertices we can simply hand calculate the combinations. Once we know what our valid pairings are we can construct a set of feasible cost moves based on our cost function by iterating through all possible pairings of # vertices and # edges. We then apply a simple DP algorithm to calculate the minimum number of planar graphs needed.
An implementation is shown below:
class PlanarGraphShop {
public:
int bestCount(int);
};
int dp[50001];
vector<int> moves;
#define INF 1 << 20
int func(int N) {
if (N == 0) return 0;
if (N < 0) return INF;
if (dp[N] != -1) return dp[N];
int res = INF;
for (int i = 0; i < moves.size() && moves[i] <= N; i++)
res <?= 1 + func(N - moves[i]);
return dp[N] = res;
}
int PlanarGraphShop::bestCount(int N) {
set<int> costs;
costs.insert(1); costs.insert(8); costs.insert(9);
for (int v = 1; v < 37; v++)
for (int e = 0; e <= 3 * v - 6; e++)
costs.insert(v*v*v + e*e);
moves = vector<int>(costs.begin(),costs.end());
memset(dp,-1,sizeof(dp));
return func(N);
}