ZOJ 2745 01-K Code dp+迭代

题意:要求长度为N的二进制数字中,它的所有字串(注意是any)中0 1的差的绝对值不大于K。

做法:从长度为1 的时候开始算起,每一次操作都是增加了一个1或者一个0,那么可以为用这个当做状态,记得状态划分时,增加末尾数字改变的是任何一个含有末尾字符的字串中0,1的数量,这里就有一个递推关系了,要当前状态的后缀字串有效,那么必须它的前面的那个字符够成的后缀字串有效,这样一来,最终会把所有字符串中的所有字串考虑进去。一开始是想考虑所有前缀串的,可是无法与状态结合起来啊。。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#define LMT 65
#define LL long long
using namespace std;
LL dp[LMT][135][135],ans;
int k,n;
void init(void)
{
    memset(dp,0,sizeof(dp));
    ans=0;
}
inline int abs(int x)
{
    return x>0?x:-x;
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        init();
        dp[1][LMT+1][LMT-1]=dp[1][LMT-1][LMT+1]=1;
        for(int i=1;i<n;i++)
         for(int j=-i+LMT;j<=i+LMT;j++)
           for(int t=-i+LMT;t<=i+LMT;t++)
           {
               int k1=j-LMT,k2=t-LMT,num;
               if(abs(k1+1)<=k&&abs(k2-1)<=k)
               {
                   num=(k1>=0?k1:0)+1;
                   dp[i+1][num+LMT][k2-1+LMT]+=dp[i][j][t];
               }
               if(abs(k1-1)<=k&&abs(k2+1)<=k)
               {
                   num=(k2>=0?k2:0)+1;
                   dp[i+1][k1-1+LMT][num+LMT]+=dp[i][j][t];
               }
           }
           for(int j=-n+LMT;j<=n+LMT;j++)
             for(int t=-n+LMT;t<=n+LMT;t++)
             ans+=dp[n][j][t];
             printf("%lld\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值