这是针对this问题。我们需要计算f(n,k),它是长度为n的二进制字符串的数量,其长度为1的最长子字符串的长度为k。我在提交递归时遇到了麻烦。
当第i位为0时,我认为我可以处理。 具体来说,当我将第i个数字视为1时,我无法将解决方案扩展到子问题f(i-1,j)。如何将两者拼接在一起?
很抱歉,如果我有点不清楚。任何指针都会有很大的帮助。感谢。
答案 0 :(得分:1)
我认为如果扩展状态空间,可以使用动态编程的变体来构建表。假设您计算f(n,k,e)定义为长度为n的不同二进制字符串的数量,最长子串为1s长度最多为k且以行中的e 1结尾。如果你计算了与给定n相关的k和e的所有可能值的f(n,k,e),那么,因为你有e分割的值,你可以计算f(n + 1,k,e) )对于k和e的所有可能值 - 当你用0或1扩展它时,n长字符串会发生什么情况取决于它此刻结束的数量为1,并且你知道因为e。
答案 1 :(得分:1)
设s是长度 k 模式的起始索引。然后s在:1到n-k。
对于每个s,我们将Sting S分成三个字符串:
PRE(s,k,n) = S[1:s-1]
POST(s,k,n)=S[s+k-1:n]
ONE(s,k,n) which has all 1s from S[s] to S[s+k-1]
PRE和POST的最长1s子串应小于k。
让
x = s-1
y = n-(s+k)-1
设NS(p,k)是总长度大于等于k的子串的方式。
NS(p,k) = sum{f(p,k), f(p,k+1),... f(p,p)}
终止条件:
NS(p,k) = 1 if p==k, 0 if k>p
f(n,k) = 1 if n==k, 0, if k > n.
对于长度为n的字符串,排列的数量使得1s的最长子字符串的大小小于k = 2 ^ n - NS(n,k)。
f(n,k) = Sum over all s=1 to n-k
{2^x - NS(x,k)}*{2^y - NS(y,k)}
即。每个前后子串的排列数的乘积,其中最长的子串小于大小k。
所以我们有一个重复的子问题,以及一大堆可以DPed的重用
稍后添加: 根据下面的评论,我想我们真的不需要进入NS。 我们可以将S(p,k)定义为
S(p,k) = sum{f(p,1), f(p,2),... f(p,k-1)}
和
f(n,k) = Sum over all s=1 to n-k
S(x,k)*S(y,k)
答案 2 :(得分:0)
我知道这是一个很老的问题,如果有人想要我可以澄清我的小答案..
这是我的代码
#include<bits/stdc++.h>
using namespace std;
long long DP[64][64];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int i,j,k;
DP[1][0]=1;
DP[1][1]=1;
DP[0][0]=1;
cout<<"1 1\n";
for(i=2;i<=63;i++,cout<<"\n")
{
DP[i][0]=1;
DP[i][i]=1;
cout<<"1 ";
for(j=1;j<i;j++)
{
for(k=0;k<=j;k++)
DP[i][j]+=DP[i-k-1][j]+DP[i-j-1][k];
DP[i][j]-=DP[i-j-1][j];
cout<<DP[i][j]<<" ";
}
cout<<"1 ";
}
return 0;
}
DP [i] [j]代表F(i,j)。
过渡/重现(难以思考):
考虑F(i,j):
1)我可以在右边放k 1s并用0分开它们 字符串+ 0 + k次&#39; 1&#39; 。 F(I-K-1,j)的 注意:k = 0表示我只在右边保持0!
2)我错过了正确的j + 1位置填充0和j&#39; 1&#39; s和所有左边不形成任何连续的长度为j的字符串!! F(i-j-1,k)(注意我用k代表两者都是因为我在我的代码中已经这样做了,你也可以定义其他变量!)