CF1353E 【K-periodic Garland】
题目大意
给你一个长度为 \(n\) 的 \(01\) 字符串,要求让这个字符串的每个 \(1\) 字符之间的距离恰好都为 \(k\) ,问至少要修改几个字符。
思路
显然这是道 dp 题。
-
\(dp_{i ,0}\) 表示到第 \(i\) 个字符为止,只让第 \(i\) 位为 \(1\),其余 \(i-1\) 位均位 \(0\) 时需要的操作次数。
-
\(dp_{i,1}\) 表示到第 \(i\) 个字符为止,让第 \(i\) 位为 \(1\),且保证在这之前合法所需要的最少操作次数。
那显然,只要维护一个前缀和 \(sum_i\) ,统计到第 \(i-1\) 个字符位置 \(1\) 的数量,那么:
\[dp_{i,0}=\begin{cases}sum_{i-1}\ \ \ \ \ \ (s_i=1)\\sum_{i-1}+1\ \ \ \ \ \ (s_i=0)\end{cases}
\]
Ps: \(s_i\) 表示字符串的第 \(i\) 位所表示的字符。
同时,我们也很容易推出另外一个转移式:
\[\mathop{dp_{i,1}}\limits_{i-k\ge1}=\begin{cases}\min(dp_{i-k,1},dp_{i-k,0}) + sum_{i-1}-sum_{i-k} \ \ \ \ \ \ (s_i=1)\\\min(dp_{i-k,1},dp_{i-k,0}) + sum_{i-1}-sum_{i-k}+1 \ \ \ \ \ \ (s_i=0)\end{cases}
\]
这很好理解,只要保证第 \(i-k\) 个位置为 \(1\) 并将 \((i-k+1)\sim (i-1)\) 中的所有 \(1\) 都设为 \(0\) 即可,这步同样可以用前缀和维护。
最后计算答案的时候,将 \(dp\) 数组从后往前扫一遍,每次在 \(dp_{i,0}\;,\;dp_{i,1}\) 中取 \(\min\) 。在扫的同时维护一个 \(num\) 表示从 \((i+1) \sim n\) 这段中 \(1\) 的数量,统计答案的时候要加上这个 \(num\),意味着吧 \((i+1) \sim n\) 中所有的 \(1\) 设为 \(0\),防止出现不合法的情况。
时间复杂度:\(\text{O}(n)\)
Code
#include<bits/stdc++.h>
using namespace std;
int read()
{
int ans=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
return ans*f;
}
const int N=1e6+5,inf=0x7f7f7f7f;
int t,n,k,dp[N][2],sum[N],ans;
char s[N];
int main()
{
memset(dp,0x7f,sizeof(dp));
// 将 dp 数组初始化,将所有可能先设为不合法
t=read();
while(t--)
{
n=read();k=read();
scanf("%s",s+1);
for(int i=1;i<=n;++i)
// 统计前缀和
sum[i]=sum[i-1]+(s[i]-'0');
ans=sum[n]; // 这里的意思是把答案初始化为:把所有的 1 都变成 0 所需要的操作次数
for(int i=1;i<=n;++i)
{
dp[i][0]=sum[i-1];
// dp[i][0] 的转移
if(i-k>=1)
dp[i][1]=min(dp[i-k][1]+sum[i-1]-sum[i-k],dp[i-k][0]+sum[i-1]-sum[i-k]);
// dp[i][1] 的转移
if(s[i]=='0')
{
if(dp[i][0]!=inf)
dp[i][0]++;
if(dp[i][1]!=inf)
dp[i][1]++;
}
}
int num=0;
// 统计答案的时候维护一个 num,防止出现不合法情况
for(int i=n;i>=1;--i)
{
ans=min(ans,min(dp[i][1]+num,dp[i][0]+num));
if(s[i]=='1')
num++;
}
for(int i=1;i<=n;++i)
// 这是这题的一个坑点,直接 memset 会 T,必须手动清空
{
sum[i]=0;
dp[i][0]=inf;
dp[i][1]=inf;
}
printf("%d\n",ans);
}
return 0;
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。