[codeforces 1353E] K-periodic Garland 为什么会想到动归dp

三世轮回 提交于 2020-10-03 00:40:31

Codeforces Round #642 (Div. 3)  参与排名人数11823

[codeforces 1353E]   K-periodic Garland   为什么会想到动归dp

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1353/problem/E

Problem Lang Verdict Time Memory
E - K-periodic Garland GNU C++17 Accepted 46 ms 12400 KB

 思路来自对数据的分析:

以n=4,k=2为例
有16种形态
0000符合题意
0001符合题意
0010符合题意
0011
0100符合题意
0101符合题意
0110
0111
1000符合题意
1001
1010符合题意
1011
1100
1101
1110
1111

动归dp的目标不是枚举所有情况,而是符合题意的情况一个都不会漏,符合题意的形态有7种
0000
0001
0010
0100
0101
1000
1010

通过对以下数据进行归纳,容易得出对应的动归dp的写法,对这7种形态,归类,找规律
1000注意,最后一个1,后面全是0
1010注意,最后一个1,后面全是0.(1010与1000有递推关系)
0100注意,最后一个1,后面全是0
0101注意,最后一个1,后面正好数据据终结.(0101与0100有递推关系)
0010注意,最后一个1,后面全是0
0001注意,最后一个1,后面正好数据据终结
0000注意,全是0

考虑如下输入数据
4 2
1111

1111变换到0000,需变动4个数据
1111变换到1000,需变动3个数据
1111变换到1010,需变动2个数据
1111变换到0100,需变动3个数据
1111变换到0101,需变动2个数据
1111变换到0010,需变动3个数据
1111变换到0001,需变动3个数据

取最小值2,
输出2

根据上述数据分析,容易得到动归dp对应的算法如下:

dp[i]记录字串[1,i]区间满足题意的周期性质,第i位为必须为1,需要更新原字符串中的值的最小个数(1变0,记1次;0变1,记1次)

AC代码如下

#include <cstdio>
#include <algorithm>
#define maxn 1000010
using namespace std;
char s[maxn];
int sum[maxn],dp[maxn];//dp[i]记录字串[1,i]区间满足题意的周期性质,第i位为必须为1,需要更新原字符串中的值的最小个数(1变0,记1次;0变1,记1次)
int main(){
	int t,n,k,i,ans;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%s",&n,&k,s+1);
		for(i=1;i<=n;i++)sum[i]=sum[i-1]+s[i]-'0';//sum[]采用前缀和的方式记录字符串中1的个数
		for(i=1;i<=n;i++)dp[i]=sum[i-1]+(s[i]=='0');//处理字串[1,i]区间,目标(第i位为1,[1,i-1]全为0),字串需要变动的个数
		for(i=k+1;i<=n;i++)//要涉及起始位置,以及之后一个周期的k个数,故每次需处理连续的k+1个数
			dp[i]=min(dp[i],dp[i-k]+sum[i-1]-sum[i-k]+(s[i]=='0'));//dp[i-k]对应字串[1,i-k]区间满足题意的周期性质,第i-k位为必须为1,需要更新原字符串中的值的最小个数(1变0,记1次;0变1,记1次).sum[i-1]-sum[i-k]对应原字串区间[i-k+1,i-1]中1的个数.(s[i]=='0'),对应,第i位为必须为1,该位必须更新的次数。
		ans=sum[n];//对应更新后的字串全是0,需要更新的个数,即原字串中的1全部变更为0
		for(i=1;i<=n;i++)
			ans=min(ans,dp[i]+sum[n]-sum[i]);//请注意,区间[i+1,n]原字串的1全部变更为0.sum[n]-sum[i]对应原字串区间[i+1,n]中1的个数.
		printf("%d\n",ans);
	}
	return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!