寻找最佳子结构

时间:2012-07-22 15:09:00

标签: c++ algorithm dynamic-programming

我正在寻找关于动态编程问题的一些指示。我找不到任何有关如何解决此类问题的相关信息。

问题

 A number is called a special number if it doesn't contain 3 consecutive 
 zeroes. i have to calculate the number of positive integers of exactly d digits 
 that are special answer should be modulo 1000000007(just for overflow in c++).

问题可以通过排列和组合轻松解决,但我想用动态编程。 我无法找到最佳的子结构或从底部到顶部的方法。

2 个答案:

答案 0 :(得分:1)

f(d,x)为最后d位数为零的最重要x位数,其中0≤x≤2。d> ; 1,我们再次发生:

f(d,0) = (f(d-1,0) + f(d-1,1) + f(d-1,2)) * 9  // f(d,0) comes from any d-1 digits patterns appended a non-zero digit 
f(d,1) = f(d-1,0) // f(d,1) comes from the d-1 digits patterns without tailing zeros appended by a zero
f(d,2) = f(d-1,1) // f(d,2) comes from the d-1 digits patterns with one tailing zero appended by a zero

对于d = 1,我们有f(1,0) = 9, f(1,1) = 0, f(1,2) = 0

原始问题的最终答案是f(d,0) + f(d,1) + f(d,2)

这是一个用于演示的简单C程序:

#include <cstdio>

const int MOD = 1000000007;
long long f[128][3];

int main() {
  int n;
  scanf("%d",&n);
  f[1][0] = 9;
  for (int i = 2 ; i <= n ; ++i) {
    f[i][0] = (f[i-1][0] + f[i-1][1] + f[i-1][2]) * 9 % MOD;
    f[i][1] = f[i-1][0];
    f[i][2] = f[i-1][1];
  }
  printf("%lld\n", (f[n][0] + f[n][1] + f[n][2]) % MOD);
  return 0;
}

答案 1 :(得分:0)

注意:我没有彻底测试我的逻辑,所以请指出我可能出错的地方。

问题的重现可以是

f(d)=f(d/2)*f(d-d/2)-( f(d/2-1)*f(d-d/2-2) + f(d/2-2)*f(d-d/2-1) ) f(0)=1;f(1)=10;f(2)=100;f(3)=999;

这里,f(i)是可以形成的特殊数字的总数,考虑到'0'可以作为第一个数字出现。因此,“d”数字的实际答案为9*f(d-1)

您可以轻松记住重复发生解决方案以制作DP解决方案。

我还没有尝试过这个解决方案的有效性,所以可能是错的。 这是我的逻辑:

对于f(d),将数字划分/分为d/2(d-d/2)个数字,添加f(d)*f(d-d/2)的乘积。现在,要删除可能在我们所做的分区中发生的无效情况,从答案中减去f(d/2-1)*f(d-d/2-2) + f(d/2-2)*f(d-d/2-1)(假设在我们制作的分区中出现三个零)。用纸和笔试试吧,你会得到它。