思路:
题目链接http://poj.openjudge.cn/practice/C17K/
状压dp。dp[i][j]表示第i - k人到第i人的状态为j的情况下前i人中最多有多少好人。
实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int dp[2][2049]; 4 struct node 5 { 6 int type, id1, id2; 7 bool f1, f2; 8 }; 9 node a[5001]; 10 bool same(bool a, bool b) 11 { 12 return (a && b) || (!a && !b); 13 } 14 int main() 15 { 16 int t, n, k; 17 cin >> t; 18 while (t--) 19 { 20 memset(dp, 0, sizeof dp); 21 cin >> n >> k; 22 string s; 23 getchar(); 24 for (int i = 1; i < n; i++) 25 { 26 getline(cin, s); 27 string tmp; 28 stringstream ss(s); 29 vector<string> v; 30 while (ss >> tmp) v.push_back(tmp); 31 if (v[2][0] == 'I') 32 { 33 a[i].type = 2; 34 a[i].id1 = atoi(v[4].c_str()); 35 a[i].id2 = atoi(v[10].c_str()); 36 a[i].f1 = v[7] == "good" ? true : false; 37 a[i].f2 = v[13] == "good" ? true : false; 38 } 39 else 40 { 41 a[i].type = 1; 42 a[i].id1 = atoi(v[3].c_str()); 43 a[i].f1 = v[6] == "good" ? true : false; 44 } 45 } 46 47 int msk = (1 << k + 1) - 1; 48 dp[0][1] = 1; 49 for (int i = 1; i < n; i++) 50 { 51 memset(dp[i & 1], 0, sizeof dp[i & 1]); 52 for (int j = 0; j < 1 << k + 1; j++) 53 { 54 if (i < k + 1 && j >= 1 << i) continue; 55 int tmp = j << 1 & msk; 56 dp[i & 1][tmp] = max(dp[i & 1][tmp], dp[i - 1 & 1][j]); 57 if (a[i].type == 1) 58 { 59 int p1 = i - a[i].id1; 60 if (same(a[i].f1, j >> p1 & 1)) 61 { 62 dp[i & 1][tmp | 1] = max(dp[i & 1][tmp | 1], dp[i - 1 & 1][j] + 1); 63 } 64 } 65 else 66 { 67 int p1 = i - a[i].id1, p2 = i - a[i].id2; 68 bool g1 = j >> p1 & 1, g2 = j >> p2 & 1; 69 if (!(same(a[i].f1, g1) && !same(a[i].f2, g2))) 70 dp[i & 1][tmp | 1] = max(dp[i & 1][tmp | 1], dp[i - 1 & 1][j] + 1); 71 } 72 } 73 } 74 int ans = 0; 75 for (int i = 0; i < 1 << k + 1; i++) 76 ans = max(ans, dp[n - 1 & 1][i]); 77 cout << ans << endl; 78 } 79 return 0; 80 }