Codeforces Round #612 (Div. 2) C. Garland 动态规划
题目链接: https://codeforces.com/contest/1287/problem/C
C. Garland
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Vadim loves decorating the Christmas tree, so he got a beautiful garland as a present. It consists of nn light bulbs in a single row. Each bulb has a number from 11 to nn (in arbitrary order), such that all the numbers are distinct. While Vadim was solving problems, his home Carp removed some light bulbs from the garland. Now Vadim wants to put them back on.
Vadim wants to put all bulb back on the garland. Vadim defines complexity of a garland to be the number of pairs of adjacent bulbs with numbers with different parity (remainder of the division by 22). For example, the complexity of 1 4 2 3 5 is 22 and the complexity of 1 3 5 7 6 4 2 is 11.
No one likes complexity, so Vadim wants to minimize the number of such pairs. Find the way to put all bulbs back on the garland, such that the complexity is as small as possible.
Input
The first line contains a single integer nn (1≤n≤1001≤n≤100) — the number of light bulbs on the garland.
The second line contains nn integers p1, p2, …, pnp1, p2, …, pn (0≤pi≤n0≤pi≤n) — the number on the ii-th bulb, or 00 if it was removed.
Output
Output a single number — the minimum complexity of the garland.
Examples
input
Copy
5
0 5 0 2 3
output
Copy
2
input
Copy
7
1 0 0 5 0 0 2
output
Copy
1
Note
In the first example, one should place light bulbs as 1 5 4 2 3. In that case, the complexity would be equal to 2, because only (5,4)(5,4) and (2,3)(2,3) are the pairs of adjacent bulbs that have different parity.
In the second case, one of the correct answers is 1 7 3 5 6 4 2.
题意:
给定一个整数n,
以及一个n的全排列,现在将全排列中的一些数字抹掉为0.
问你将抹掉的数字以任意位置填回去后,槽糕值最低是多少?
定义一个排列的糟糕值为这样的位置i的个数:
a[i] 和a[i+1] 的奇偶性不同。
思路:
很容易想到用DP来解决该问题:
我们定义DP 状态为:
\(dp[i][j][0]\) 到第i个位置,还剩j个偶数没用,第i个位置是偶数的最小糟糕值。
\(dp[i][j][1]\) 到第i个位置,还剩j个偶数没用,第i个位置是奇数的最小糟糕值。
初始化:
如果n大于1,并且第一个数a[1] 为0或者偶数,
令\(dp[1][n/2-1][0]=0\)
如果第一个数a[1] 为0或者奇数,
令\(dp[1][n/2][1]=0\)
转移方程见代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
template<typename T> inline T max(T a, T b) {return a > b ? a : b;}
template<typename T> inline T min(T a, T b) {return a < b ? a : b;}
template<typename T> inline T abs(T a) {return a > 0 ? a : -a;}
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 110;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n;
int a[maxn];
int dp[maxn][maxn][3];
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
cin >> n;
repd(i, 1, n)
{
cin >> a[i];
}
repd(i, 1, n)
{
repd(j, 0, n)
{
dp[i][j][0] = dp[i][j][1] = inf;
}
}
if (n > 1 && a[1] % 2 == 0)
{
dp[1][n / 2 - 1][0] = 0;
}
if (a[1] == 0 || a[1] & 1)
{
dp[1][n / 2][1] = 0;
}
repd(i, 2, n)
{
repd(j, 0, n / 2)
{
if (j > 0 && !(a[i] & 1))
{
dp[i][j - 1][0] = min(dp[i][j - 1][0], dp[i - 1][j][1] + 1);
dp[i][j - 1][0] = min(dp[i][j - 1][0], dp[i - 1][j][0]);
}
if (i + j <= n && (a[i] == 0 || (a[i] & 1)))
{
dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j][1]);
dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j][0] + 1);
}
}
}
cout << min(dp[n][0][0], dp[n][0][1]) << endl;
return 0;
}