http://codeforces.com/contest/1287/problem/C
思路:
dp[k][h][w][z] 表示剩余0-k节点,基数点剩余h个,偶数点剩余w个,k点为z(奇/偶) 的情况下的最优值。
其中w可以省略掉因为可以根据k和h计算出w,为了方便写计算留下了w。
代码:
#include <iostream> #include <string> #include <string.h> #include <stdio.h> #include <algorithm> #include <map> using namespace std; const int N = 101; int a[N]; int dp[N][N][N][2]; int n; int dfs(int k, int h, int w, int z) { if (dp[k][h][w][z] != -1) { return dp[k][h][w][z]; } if (k == 0) { if ((z == 1 && (a[k] == 0 || a[k]&0x01)) && h > 0) return (dp[k][h][w][z] = 0); if ((z == 0 && (a[k] == 0 || !(a[k]&0x01))) && w > 0) return (dp[k][h][w][z] = 0); return (dp[k][h][w][z] = N); } dp[k][h][w][z] = N; if(a[k] == 0) { if (z == 1 && h > 0) { if (h > 1) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h-1, w, 1)); } if (w > 0) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h-1, w, 0) + 1); } } if (z == 0 && w > 0) { if (w > 1) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h, w-1, 0)); } if (h > 0) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h, w-1, 1) + 1); } } } else if(a[k]&0x01) { if (z == 1 && h > 0) { if (h > 1) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h-1, w, 1)); } if (w > 0) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h-1, w, 0) + 1); } } } else { if (z == 0 && w > 0) { if (w > 1) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h, w-1, 0)); } if (h > 0) { dp[k][h][w][z] = min(dp[k][h][w][z], dfs(k-1, h, w-1, 1) + 1); } } } //cout << k <<" " <<h << " " << w << " " << z << " " << dp[k][h][w][z] << endl; return dp[k][h][w][z]; } int main() { while(cin>>n) { for (int i = 0; i < n; ++i) { cin>>a[i]; } if (n == 1) { cout << 0 << endl; continue; } if (n == 2) { cout << 1 << endl; continue; } memset(dp, -1, sizeof(dp)); int h = n >> 1; if (n&0x01) { h ++; } cout << min(dfs(n-1, h, n-h, 1), dfs(n-1, h, n-h, 0)) << endl; } return 0; }