POJ 2978 - Colored stones
http://poj.org/problem?id=2978
概要
\(m\)
個の石が一直線に並べられており,それぞれ \(x_i\)
の色で塗られている.
色は全部で \(k\)
種類ある.
任意の同じ色の2つの石について,その2つの石の間にそれとは異なる色の石が無いようにしたい. このとき,取り除く必要がある石の最小値を答える.
制約
\(1 \le m \le 100\)
\(1 \le k \le 5\)
\(1 \le x_i \le k\)
解法
$$\mathit{dp}(i, j, s) = \mbox{\(i\) 番目の石までで,最後の色が \(j\) で今までに使った色の状態が \(s\) のときの最小値}$$
という DP 表を埋めて \(\mbox{min}_{1 \le j \le k, 0 \le s < 2^k}\{\mathit{dp}(m, j, s)\}\)
が答え.
poj/2978.cc1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 int main() 6 { 7 int M, K; 8 while (cin >> M >> K && M != 0) { 9 static int dp[100][5][1<<5]; 10 static const int INF = 10000000; 11 for (int i = 0; i < M; i++) { 12 for (int j = 0; j < K; j++) { 13 fill_n(dp[i][j], 1<<K, INF); 14 } 15 } 16 17 static int a[100]; 18 for (int i = 0; i < M; i++) { 19 cin >> a[i]; 20 --a[i]; 21 } 22 23 for (int j = 0; j < K; j++) { 24 if (j == a[0]) { 25 dp[0][j][1<<j] = 0; 26 } else { 27 dp[0][j][1<<j] = 1; 28 } 29 } 30 for (int i = 0; i < M-1; i++) { 31 for (int j = 0; j < K; j++) { 32 for (int k = 0; k < (1<<K); k++) { 33 if (!(k & (1<<j))) { 34 continue; 35 } 36 dp[i+1][j][k] = min(dp[i+1][j][k], dp[i][j][k] + (a[i+1] != j)); 37 if (!(k & (1<<a[i+1]))) { 38 const int s = k | (1<<a[i+1]); 39 dp[i+1][a[i+1]][s] = min(dp[i+1][a[i+1]][s], dp[i][j][k]); 40 } 41 } 42 } 43 } 44 45 int ans = INF; 46 for (int j = 0; j < K; j++) { 47 for (int k = 0; k < (1<<K); k++) { 48 ans = min(ans, dp[M-1][j][k]); 49 } 50 } 51 cout << ans << endl; 52 } 53 return 0; 54 }