#include #include #include using namespace std; /* I use -2 in the cache to mean -- problem not done yet, since -1 is a legal answer. */ class Solution { public: int minCost(vector& houses, vector >& cost, int m, int n, int target); vector H; vector< vector > C; int DP(int index, int target, int prev); vector < vector < vector > > Cache; }; int Solution::DP(int index, int t, int prev) { int i; int orig; int v; int mx; /* printf("Called DP(%d,%d,%d).", index, t,prev); for (i = 0; i < H.size(); i++) printf(" %d", H[i]); printf("\n"); */ /* Base cases. */ if (index == H.size() && t == 0) return 0; if (index == H.size()) return -1; if (Cache[index][t][prev] != -2) return Cache[index][t][prev]; orig = H[index]; /* Your first case is if house[index] is already painted. There are three cases here: */ if (orig != -1) { if (orig != prev) { if (t == 0) { /* 1. It starts a new group, but t == 0, so it's impossible. */ mx = -1; } else { /* 2. It starts a new group, so you recurse on t-1. */ mx = DP(index+1, t-1, orig); } } else { mx = DP(index+1, t, orig); /* 3. It continues the previous color, and you recurse. */ } /* Your second case is if house[index] is unpainted. You don't have to set H[index], by the way. That's just useful for debugging. */ } else { if (t == 0) { /* If you can't create a new group, then you can */ H[index] = prev; /* only color it the same color as the previous house. */ mx = DP(index+1, t, prev); if (mx != -1) mx += C[index][prev]; } else { /* Otherwise, test all colors */ mx = -1; for (i = 0; i < C[index].size(); i++) { H[index] = i; v = DP(index+1, t - ((i == prev) ? 0 : 1), i); if (v != -1) { v += C[index][i]; if (mx == -1 || v < mx) mx = v; } } } } H[index] = orig; /* Reset the house's color (this is only for debugging -- see above) */ /* printf("Return DP(%d,%d,%d).", index, t,prev); for (i = 0; i < H.size(); i++) printf(" %d", H[i]); printf(" -- %d\n", mx); */ Cache[index][t][prev] = mx; /* Put the answer into the cache and return. */ return mx; } int Solution::minCost(vector& h, vector >& c, int m, int n, int t) { int i, j; H = h; C = c; Cache.resize(m); for (i = 0; i < m; i++) { Cache[i].resize(t+1); for (j = 0; j < Cache[i].size(); j++) Cache[i][j].resize(n+1, -2); } for (i = 0; i < H.size(); i++) H[i]--; // Decrement the house numbers so -1 means unpainted. return DP(0, t, n); // And that way c[i][j] is the cost of painting } // house i to color j. int main() { int m, n, t; int i, j, k; vector h; vector < vector > c; Solution s; cin >> m >> n >> t; h.resize(m); c.resize(m); for (i = 0; i < m; i++) c[i].resize(n); for (i = 0; i < m; i++) cin >> h[i]; for (i = 0; i < m; i++) for (j =0; j < n; j++) cin >> c[i][j]; cout << s.minCost(h, c, m, n, t) << endl; /* for (i = 0; i < s.Cache.size(); i++) { for (j = 0; j < s.Cache[i].size(); j++) { for (k = 0; k < s.Cache[i][j].size(); k++) { if (s.Cache[i][j][k] != -2) { printf("s.Cache[%d][%d][%d] = %d\n", i, j, k, s.Cache[i][j][k]); } } } } */ return 0; }