C. Garland
好久没发博客了,发个博客证明我活着!!!
又是dp,设dp[i][j][k][2],代表填到第i位,有j个奇数,k个偶数,如果是1表示当前填的数是奇数,如果是0表示当前填的数是偶数。那么转移就简单了。
如果当前位置能够随意填数,那么我们需要转移两个dp[i][j][k][0] 和 dp[i][j][k][1],dp[i][j][k][0] = min(dp[i-1][j][k-1][0],dp[i-1][j][k-1][1]+1) ;
同理dp[i][j][k][1],如果该位置数已经固定,那么dp[i][j][k][0] = min(dp[i-1][j][k][0],dp[i-1][j][k][1]+1);同理dp[i][j][k][1];
#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;
int a[maxn],dp[maxn][maxn][maxn][2],pre[maxn];
int main()
{
int n; cin>>n;
int one = 0 , zero = 0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]!=0) { if(a[i]%2) one++; else zero++; pre[i] = pre[i-1]; }
else { pre[i] = pre[i-1]+1; }
}
int x = (n+1)/2;
one = x - one;
zero = n - x - zero;
memset(dp,n,sizeof(dp));
dp[0][0][0][0] = 0 ; dp[0][0][0][1] = 0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=one;j++)
{
for(int k=0;k<=zero;k++)
{
if(a[i]!=0)
{
if(j+k<=pre[i])
{
if(a[i]%2) dp[i][j][k][1] = min(dp[i-1][j][k][0]+1,dp[i-1][j][k][1]);
else dp[i][j][k][0] = min(dp[i-1][j][k][0],dp[i-1][j][k][1]+1);
}
}
else
{
if(j+k<=pre[i])
{
if(k>0) dp[i][j][k][0] = min(dp[i-1][j][k-1][0],dp[i-1][j][k-1][1]+1);
if(j>0) dp[i][j][k][1] = min(dp[i-1][j-1][k][0]+1,dp[i-1][j-1][k][1]);
}
}
}
}
}
cout<<min(dp[n][one][zero][0],dp[n][one][zero][1])<<endl;