• 【DP】E. K-periodic Garland


    E. K-periodic Garland

    题意:给定长度为n的01字符串,每次操作可以改变一个字符的状态,问使字符串中相邻1的距离为k的最小操作次数

    思路:

    DP。

    (pre[i])记录前(i)项中(1)的个数

    (dp[i][0])为使得前(i)项都合法,第(i)位为(0)时的最小操作次数

    (dp[i][1])为使得前(i)项都合法,第(i)位为(1)时的最小操作次数

    那么转移方程

    $dp[i][0]=min(dp[i-1][0],dp[i-1][1])+(s[i]==1) $

    因为第(i)项为(0)时对合法性无影响,其合法性可以直接从(dp[i-1][0]或者dp[i-1][1])转移过来,操作次数更新由(s[i]==1)负责,若(s[i])本身就为0,则新增0次操作,否则新增1次操作

    (dp[i][1]=min(dp[i-k][1]+pre[i-1]-pre[i-k],pre[i-1])+(s[i]==0))

    当第(i-k)项合法时,要使第(i)项为(1)时合法,则要保证第(i-k+1)项到第(i-1)项都为(0),第(i)项才能为(1)(此时(pre[i-1]-pre[i-k]=0)),(dp[i][1])的状态才能从(dp[i-k][1])转移过来;或者从“令(1)(i-1)项全为(0),使得第(i)项为整个序列的第一个(1)”的状态转移过来。操作次数更新由(s[i]==0)负责,若(s[i])本身就为1,则新增0次操作,否则新增1次操作

    最后注意输入的是字符数组

    void solve() {
    	int n, k;
    	cin >> n >> k;
    	cin >> s+1;
    	for (int i = 1; i <= n; i++)
    		pre[i] = pre[i - 1] + (s[i] == '1');
    	for (int i = 1; i <= n; i++) {
    		int p = max(0, i - k);
    		dp[i][0] = min(dp[i - 1][0], dp[i - 1][1]) + (s[i] == '1');
    		dp[i][1] = min(dp[p][1] + pre[i - 1] - pre[p], pre[i - 1]) + (s[i] == '0');
    	}
    	cout << min(dp[n][0], dp[n][1]) << endl;
    	for (int i = 0; i <= n; i++) {
    		dp[i][1] = 0;
    		dp[i][0] = 0;
    		pre[i] = 0;
    	}
    }
    
  • 相关阅读:
    TCP/IP
    Socket通信
    Dubbo详解
    高并发详解
    P3-DataBase
    JAVA基础学习之路(十)this关键字
    [SHELL]输出目录下所有的可执行文件,批量创建用户
    JAVA基础学习之路(八)[1]String类的基本特点
    [MYSQL][2]索引
    [MYSQL][1]创建,修改,删除表
  • 原文地址:https://www.cnblogs.com/streamazure/p/12896935.html
Copyright © 2020-2023  润新知