Codeforces Round 642 (Div. 3) E. K-periodic Garland(DP+前缀和)

题目链接

https://codeforces.com/contest/1353/problem/E

思路

d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1]分别表示第 i i i个字符是 0 0 0或者 1 1 1时的前 i i i个字符组成的花环所需的最少操作次数。

如果第 i i i个字符变为 1 1 1,分为两种情况:第一种情况是第 i − k i-k ik个字符必须为 1 1 1,且 [ i − k + 1 , i − 1 ] [i-k+1,i-1] [ik+1,i1]中间的字符必须为 0 0 0。第二种情况是前 i − 1 i-1 i1个字符全部为 0 0 0

如果第 i i i个字符变为 0 0 0,则前 i − 1 i-1 i1个字符可以为 0 0 0 1 1 1

我们令 s u m [ i ] sum[i] sum[i]表示前 i i i个字符中 1 1 1的个数。

状态转移方程为:

i − k ≥ 0 i - k \ge 0 ik0时: d p [ i ] [ 1 ] = m i n ( s u m [ i − 1 ] , d p [ i − k ] [ 1 ] + ( s u m [ i − 1 ] − s u m [ i − k ] ) ) + ( s [ i ] ≠ ′ 1 ′ ) dp[i][1] = min(sum[i - 1], dp[i - k][1] + (sum[i - 1] - sum[i - k])) + (s[i] \ne '1') dp[i][1]=min(sum[i1],dp[ik][1]+(sum[i1]sum[ik]))+(s[i]=1)

i − k < 0 i - k < 0 ik<0时: d p [ i ] [ 1 ] = s u m [ i − 1 ] + ( s [ i ] ≠ ′ 1 ′ ) dp[i][1] = sum[i - 1] + (s[i] \ne '1') dp[i][1]=sum[i1]+(s[i]=1)

d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] ) + ( s [ i ] ≠ ′ 0 ′ ) dp[i][0] = min(dp[i - 1][0], dp[i - 1][1]) + (s[i] \ne '0') dp[i][0]=min(dp[i1][0],dp[i1][1])+(s[i]=0)

时间复杂度: O ( n ) O(n) O(n)

代码

#include 

using namespace std;

#define int long long
#define double long double

typedef long long i64;
typedef unsigned long long u64;
typedef pair<int, int> pii;

const int N = 1e6 + 5, M = 5e5 + 5;
const int mod = 998244353;
const int inf = 0x3f3f3f3f3f3f3f3f;

std::mt19937 rnd(time(0));

int n, k;
int sum[N], dp[N][2];
char s[N];
void solve()
{
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> s[i];
	}
	for (int i = 1; i <= n; i++)
	{
		sum[i] = sum[i - 1] + (s[i] == '1');
	}
	for (int i = 1; i <= n; i++)
	{
		dp[i][0] = dp[i][1] = inf;
	}
	for (int i = 1; i <= n; i++)
	{
		if (i - k >= 0)
			dp[i][1] = min(sum[i - 1], dp[i - k][1] + (sum[i - 1] - sum[i - k])) + (s[i] != '1');
		else dp[i][1] = (sum[i - 1]) + (s[i] != '1');
		dp[i][0] = min(dp[i - 1][0], dp[i - 1][1]) + (s[i] != '0');
	}
	cout << min(dp[n][0], dp[n][1]) << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

你可能感兴趣的:(ACM—DP,动态规划,算法)