Codeforces Round #612 (Div. 2) C. Garland【dp】

在这里插入图片描述

添加链接描述
题目大意:有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]));
 } 
发布了39 篇原创文章 · 获赞 0 · 访问量 1105

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/103861399