01-K Code ZOJ

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2745

终于AC了,纠结了一天的一道题。。。。

题意: 给一个长度为N的string , 需要往里面填充一些0、1,约束条件就是N的任意一个substring的中0的个数和1的个数之差不能超过K。

算法: DP

分析: 一开始没有看到substring 。 以为就是要求整个序列0的个数和1 的个数不超过K,一敲,果断WA,看了一下N的值,发现会超出int,该了long long ,2交,还是WA。。 重新看题目,发现是substring,才意识到自己错了。 。。 想了半天,经分析得:对于每一个状态下的后一位数是应该放0 还是1 ,其实就是取决于包括本字母在内的整个字符串的后缀中0、1的个数差是否满足条件,那只需要记录下每个状态下,前一个串的后缀中0、1差的最大值就可以了,因为状态就得到了。。

dp[i][k1][k2] 表示前i个字符串中,后缀满足max{ |0| - |1| }=k1 ; max{|1| - |0|} = k2 ;的种数;


代码:

/*
ZOJ 2745 01-K Code
Tips: DP
Language C++ 
*/ 
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int N,K;
long long dp[65][65*2][65*2] ;

void DP()
{
	memset(dp,0,sizeof(dp));
	dp[1][64][66] = 1 ;
	dp[1][66][64] = 1 ;
	for(int i=1;i<=N;i++)
	{
		for(int j=-i+65;j<=i+65;j++)
		{
			for(int k=-i+65;k<=i+65;k++)
			{
				int k1 = j-65; int k2 = k-65 ;			//考虑到k1可能为负值,因此加上一个数。 
				if(abs(k1+1)<=K && abs(k2-1)<=K)
				{
					long long num = (k1+1>1 ? k1 : 0 )+ 1 ;
					dp[i+1][num+65][k2-1+65] += dp[i][j][k] ;	
				}
				if(abs(k1-1)<=K && abs(k2+1)<=K){
					long long num = (k2+1>1 ? k2 : 0 ) + 1 ;
					dp[i+1][k1-1+65][num+65] += dp[i][j][k] ;	
				}
			}	
		}	
	}
	long long ans= 0 ;
	for(int i=-N+65;i<=N+65;i++)
		for(int j=-N+65;j<=N+65;j++)
		{
			ans += dp[N][i][j] ;	
		}
	printf("%lld\n",ans);	
}

int main()
{
	while(scanf("%d %d",&N,&K)!=EOF)
	{
		DP();
	}	
	return 0 ;	
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值