添加链接描述
题目大意:有n个数的排列,数字在1~n之间,现在挖空了这个序列了几个位置,输入0代表这个位置为空,你可以从剩下的数字里随意挑选来填充这个序列,但是相邻两个数字如果是一奇一偶形式的话会形成1个复杂度,怎样填充能使整个序列的复杂度最小,输出这个最小的复杂度。
思路:比赛时一直想着如何贪心,结果也没贪出来,dp【i】【j】【0】表示第i位是偶数,前i位有j个奇数时的最小复杂度,同理dp【i】【j】【1】表示第i位是奇数,前i位有j个奇数时的最小复杂度.
#include<bits/stdc++.h>
const int INF=0x3f3f3f3f;
using namespace std;
int a[105],n,dp[105][105][2],qi=0;//qi记录的是还剩下几个奇数可以选
int main()
{
scanf("%d", &n);
qi=(n+1)/2;
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
if(a[i]) {
if(a[i]&1) --qi;
}
}
memset(dp,INF,sizeof(dp));
dp[0][0][0]=0;
dp[0][0][1]=0;
for(int i=1;i<=n;++i)
{
if(a[i])//如果该位置已填
{
int t=a[i]&1;
for(int j=0;j<=min(qi,i-1);++j) dp[i][j][t]=min(dp[i-1][j][t],dp[i-1][j][1-t]+1);
}
else {//如果还位置未填,即为0
for(int j=1;j<=min(qi,i);++j) dp[i][j][1]=min(dp[i-1][j-1][1],dp[i-1][j-1][0]+1);//假设该位填的是奇数
for(int j=0;j<=min(qi,i-1);++j) dp[i][j][0]=min(dp[i-1][j][1]+1,dp[i-1][j][0]);//假设该位填的是偶数
}
}
printf("%d\n",min(dp[n][qi][0],dp[n][qi][1]));
}