zoukankan      html  css  js  c++  java
  • E. K-periodic Garland

    题意:你被给予了一个n个灯的花圈,灯的状态由长度为n的字符串组成,字符串s的第i个字母为'0',表示这个灯关闭,为'1',表示这个灯开着。你被给予了一个正整数k。
    每一个操作,你可以选择一个灯泡,并且改变它的状态。
    一个周期为k的花圈如果是合法的,意味着每一对相邻的开着的灯泡的距离为k,考虑k = 3的情况,"00010010"是合法的。

    分析:题目中要求每一对开着的灯泡的距离为k,但是这个花圈的左右两边可以有超过k个灯泡是关闭,只要中间连续的开的灯泡是合法的即可,比如"00010010"是合法的,只要它出现的连续的开着的灯泡是距离为k的。如何用最少的dp状态覆盖整个问题呢?比如出现前面多余k的关闭的灯泡的情况,
    所以我们要定义两个状态来组合这些情况。

    f[i][0]:前i项合法,第i位为0的最少操作次数。//这个状态能覆盖左右两端多余k个关闭的灯泡的状态
    //因此它可以从f[i - 1][0]转移过来,右端是多个0,也可以从f[i - 1][1]转移过来,第i个位置的灯泡可以关闭
    它的状态转移方程为f[i][0] = min(f[i - 1][0],f[i - 1][1]) + (s[i] == 1)

    f[i][1]:前i - 1项合法,第i位为1的最少操作次数。//如何考虑这个状态覆盖的情况
    前i项合法,第i位为1的操作次数,它可以覆盖左边全是关闭的灯的状态,从sum[i - 1]转移过来,即前面灯泡都要关闭,也可以从f[i - k][1]转移过来,
    再从f[i - k][1]转移过来的时候,中间的灯泡是需要关闭的,即sum[i - 1] - sum[i - k]。
    //仔细思考下,f[i][0]从f[i - 1][0]转移的时候,是可以覆盖右边很多个关闭灯泡的情况的

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 1000005;
    const int INF = 0x3f3f3f3f;
    char g[N];
    int a[N], sum[N];
    int f[N][2];
    int main()
    {
    	int t;
    	scanf("%d", &t);
    
    	while (t--)
    	{
    		int n, k;
    		scanf("%d%d", &n, &k);
    		scanf("%s", g + 1);
    
    		for (int i = 1; i <= n; ++i)
    		{
    			if (g[i] == '1') a[i] = 1;
    			else a[i] = 0;
    		}
    
    		for (int i = 1; i <= n; ++i)
    		{
    			sum[i] = sum[i - 1] + a[i];
    		}
    
    		for (int i = 1; i <= n; ++i)
    		{
    			int p = max(0, i - k);
    			f[i][0] = min(f[i - 1][0], f[i - 1][1]) + (a[i] == 1);
    			f[i][1] = min(sum[i - 1], f[p][1] + sum[i - 1] - sum[p]) + (a[i] == 0);
    		}
    
    		printf("%d
    ", min(f[n][0], f[n][1]));
    		for (int i = 0; i <= n; ++i)	f[i][0] = f[i][1] = 0;
    	}
    
    	return 0;
    }
    
    
  • 相关阅读:
    We Never Told Him He Couldn't Do It
    我是天蝎
    学习生活,有感动的时候
    .NET中AOP方便之神SheepAspect
    Effective Java (类和接口)
    Step By Step(Java 系列的目录)
    Linux Shel高级技巧(目录)
    Linux Shell经典实例解析Oracle启动脚本(下)
    Java和C++在细节上的差异(目录)
    Linux Shell经典实例解析Oracle启动脚本(上)
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/12894432.html
Copyright © 2011-2022 走看看