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 }

 

posted @ 2020-05-21 12:03  Linkss  阅读(350)  评论(0编辑  收藏  举报