zoukankan      html  css  js  c++  java
  • codeforces 1353E 1353F DP

    E. K-periodic Garland

    题目大意:给定一个长度为n的01串,给定一个值k,每次可以把该字符串中的任意一个字符变成0或者1,问至少操作多少次可以满足任意相邻两个1之间的长度为k。

    这个题目的解法是dp,看过题解一开始也没看懂,这个要自己多模拟几遍,不然很有肯能看题解都看不懂(可能因为我菜叭)

    dp[i][0]和dp[i][1]表示第i个字符为0或者1且前i个字符都满足的最小操作次数。

    假设第i个字符为0(这个0是我们假设的,在原字符串中可能为0也可能为1),由于前i-1个字符是满足题意的,也就是说在前i个字符中,第i个字符是最后一个字符,那么一定满足题意,因为在01串的末尾不管加多少个0这个字符串都是合法的,所以dp[i][0]=min(dp[i-1][0],dp[i-1][1])+(str=='1'),也就是前i-1个满足条件的最小操作次数加上第i个字符是否需要改变。

    假设第i个字符为1,有两种情况,第一种情况就是该字符前面存在有1,那么必须第i-k个字符为1,且前i-k个字符满足题意,并且第i-k+1个到第i-1个字符全为0才能满足题意。第二种情况就是该字符前面全是0,那么就要满足前i-1个字符全为0,即可满足题意,所以我们就要取这两种情况中操作次数较小的一种。

    所以综合一下,我们可以得到dp的状态转移方程(ans[i]表示前i个字符中1的个数)

    dp[i][0]=min(dp[i-1][0],dp[i-1][1])+(str[i-1]=='1');
    dp[i][1]=min(ans[i-1],dp[p][1]+ans[i-1]-ans[p])+(str[i-1]=='0');
     1 #include <iostream>
     2 #include <cstring>
     3 #include <string>
     4 #include <algorithm>
     5 #include <queue>
     6 #include <stack>
     7 #include <stdio.h>
     8 #include <cmath>
     9 #include <string.h>
    10 
    11 using namespace std;
    12 #define ll long long
    13 static const int WHITE=0;
    14 static const int GRAY=1;
    15 static const int BLACK=2;
    16 static const int INF=0x3f3f3f3f;
    17 int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}
    18 int lcm(int a,int b){return a*b/gcd(a,b);}
    19 ll Pow(ll a,ll b,ll mod){if(b==0) return 1%mod; ll sum=1; a=a%mod; while(b>0) { if(b%2==1) sum=(sum*a)%mod; b/=2; a=(a*a)%mod;}return sum;}
    20 
    21 int dp[1000005][2];
    22 int ans[1000005];
    23 string str;
    24 void init(int n)
    25 {
    26     for(int i=0;i<=n;i++)
    27     dp[i][0]=dp[i][1]=0;
    28     ans[0]=0;
    29     for(int i=1;i<=str.size();i++)
    30     ans[i]=ans[i-1]+(str[i-1]=='1');
    31 }
    32 
    33 int main()
    34 {
    35     freopen("C:\Users\16599\Desktop\in.txt","r",stdin);
    36     int _;
    37     cin>>_;
    38     while(_--)
    39     {
    40         int n,k;
    41         cin>>n>>k;
    42         cin>>str;
    43         init(n);
    44         for(int i=1;i<=str.size();i++)
    45         {
    46             int p=max(0,i-k);
    47             dp[i][0]=min(dp[i-1][0],dp[i-1][1])+(str[i-1]=='1');
    48             dp[i][1]=min(ans[i-1],dp[p][1]+ans[i-1]-ans[p])+(str[i-1]=='0');
    49         }
    50         cout<<min(dp[n][0],dp[n][1])<<endl;
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    Javascript高级篇-Function对象
    Object类、instanceof
    [一]Head First设计模式之【策略模式】(鸭子设计的优化历程)
    匿名内部类
    设计模式之单例模式
    长江商业评论读书笔记
    [转]Freemarker数据类型转换
    面向对象编程——概论(一)
    IP地址处理模块IPy
    系统性能模块psutil
  • 原文地址:https://www.cnblogs.com/zlhdbk/p/12928259.html
Copyright © 2011-2022 走看看