0
A
回答
1
动态编程可以在这里应用。
假设你知道n = k的非禁止序列的数量。现在如果你添加另一个字母,那么组合的数量变成3k。但是,您必须丢弃被禁止的新组合。
任何序列的最后两个字母可以是:
ab
ac
bc
ba
ca
cb
bb
aa
cc
表格,您所提供的系列,似乎 组合的数量丢弃其中(k + 1)=(对新增加的数量k)
编辑: 这是为什么呢? 从3k组合中,我们首先丢弃k个组合,说出所有先前的序列,我们将丢弃1/3。
现在,在这些k个组合被丢弃的情况下,有几个组合在最后有一个重复的字母(aa,bb或cc)。我们不必丢弃这些序列。
这样的序列的数量应该等于(k-1)的非禁止序列的数量,因为对于我们为n = k所做的每个新序列,我们可以只有一个重复字母的新序列。
Hence if f(k) = number of unforbidden combinations for n = k,
then f(k + 1) = 3f(k) - [f(k)-f(k-1)].
For example for n=3 the number of sequences with repeated letter at the end shall be 9.
For n=4 the number of sequences with repeated letter at the end shall be 21.
... and so on.
2
1
这样如何动态规划方法,其中C[x,y]
意味着数长度x
的未被禁止的字符串,其中与两个炭序列y
结束:
C [n, 'AA'] = C[n-1, 'AA'] + C[n-1, 'AB'] + C[n-1, 'AC']
C [n, 'AB'] = C[n-1, 'BA'] + C[n-1, 'BB']
C [n, 'AC'] = C[n-1, 'CA'] + C[n-1, 'CB'] + C[n-1, 'CC']
C [n, 'BA'] = C[n-1, 'AA'] + C[n-1, 'AB'] + C[n-1, 'AC']
C [n, 'BB'] = C[n-1, 'BA'] + C[n-1, 'BB'] + C[n-1, 'BC']
C [n, 'BC'] = C[n-1, 'CA'] + C[n-1, 'CB'] + C[n-1, 'CC']
C [n, 'CA'] = C[n-1, 'AA'] + C[n-1, 'AB'] + C[n-1, 'AC']
C [n, 'CB'] = C[n-1, 'BA'] + C[n-1, 'BB'] + C[n-1, 'BC']
C [n, 'CC'] = C[n-1, 'CA'] + C[n-1, 'CB'] + C[n-1, 'CC']
具有边界条件n >= 3, C[3, x] = 3, C[3, 'AB'] = 2
?
而且一个简单的程序,不知道是否正确,但果然冒险一些downvoting,如果它是错的,嘿嘿:)
#include <iostream>
unsigned int C[100][9];
// AA 0
// AB 1
// AC 2
// BA 3
// BB 4
// BC 5
// CA 6
// CB 7
// CC 8
void
calc (unsigned int n) {
unsigned int i;
for (i = 0; i < 9; ++i)
C[3][i] = 3;
C[3][1] = 2;
for (i = 4; i <= n; ++i) {
C[i][0] = C[i-1][0] + C[i-1][1] + C[i-1][2];
C[i][1] = C[i-1][3] + C[i-1][4];
C[i][2] = C[i-1][6] + C[i-1][7] + C[i-1][8];
C[i][3] = C[i-1][0] + C[i-1][1] + C[i-1][2];
C[i][4] = C[i-1][3] + C[i-1][4] + C[i-1][5];
C[i][5] = C[i-1][6] + C[i-1][7] + C[i-1][8];
C[i][6] = C[i-1][0] + C[i-1][1] + C[i-1][2];
C[i][7] = C[i-1][3] + C[i-1][4] + C[i-1][5];
C[i][8] = C[i-1][6] + C[i-1][7] + C[i-1][8];
}
}
// C [n, 'AA'] = C[n-1, 'AA'] + C[n-1, 'AB'] + C[n-1,'AC']
// C [n, 'AB'] = C[n-1, 'BA'] + C[n-1, 'BB']
// C [n, 'AC'] = C[n-1, 'CA'] + C[n-1, 'CB'] + C[n-1, 'CC']
// C [n, 'BA'] = C[n-1, 'AA'] + C[n-1, 'AB'] + C[n-1, 'AC']
// C [n, 'BB'] = C[n-1, 'BA'] + C[n-1, 'BB'] + C[n-1, 'BC']
// C [n, 'BC'] = C[n-1, 'CA'] + C[n-1, 'CB'] + C[n-1, 'CC']
// C [n, 'CA'] = C[n-1, 'AA'] + C[n-1, 'AB'] + C[n-1, 'AC']
// C [n, 'CB'] = C[n-1, 'BA'] + C[n-1, 'BB'] + C[n-1, 'BC']
// C [n, 'CC'] = C[n-1, 'CA'] + C[n-1, 'CB'] + C[n-1, 'CC']
int
main() {
for (unsigned int i = 3; i < 10; ++i) {
calc (i);
unsigned int s = 0;
for (unsigned int j = 0; j < 9; ++j)
s += C[i][j];
std::cout << s << " ";
}
}
0
对于i >= 2
:
让same[i]
是允许的数量(即不禁止)长度为i
的字符串,以两个相同的字符结尾。
让diff[i]
为长度为i
的允许字符串的数量,以两个不同的字符结尾。
然后same[2] = 3
,diff[2] = 6
,并为i >= 2
,
same[i+1] = same[i] + diff[i]
diff[i+1] = 2 * same[i] + diff[i]
我们要的是n[i] = s[i] + d[i]
;上面的公式给我们
n[2] = 9
n[i+1] = 2 * n[i] + n[i-1]
有了这个,你可以在基本上是线性的时间计算n[i]
。
相关问题
- 1. 计划 - 如何在字符串中查找字符索引
- 2. 无效字符“故宫安装” nodemailer
- 3. 查找字符串中的数字字符串,并计数
- 4. 查找字符串 - 计数位置
- 5. 查找字符串
- 6. 查找字符串
- 7. 查找字符串
- 8. 查找字符串
- 9. 查找字符串
- 10. 查找字符串
- 11. 查找字符串
- 12. 查找字符串
- 13. 查找字符串
- 14. 查找字符串
- 15. 查找字符串
- 16. 查找字符串
- 17. 查找字符串
- 18. 查找字符串
- 19. 查找字符串
- 20. 查找字符串
- 21. 故宫列名
- 22. PLT计划:评估一个字符串或字符串列表?
- 23. 在球拍计划中读取字符串中的字符串
- 24. 查找字符串中的字符串
- 25. 在字符串中查找字符串
- 26. 查找字符串中的字符串
- 27. 查找字符串中的字符串
- 28. 在字符串中查找字符串
- 29. 查找网址计划
- 30. 字符串故障
不知道这是否是作弊,但我做了什么是采取蛮力的第一个解决方案,并通过http://oeis.org/并看看你是否有任何点击。 –
作为一般线索,当处理计数访问问题时,答案通常是数学公式或某种动态编程或两者的组合......并且从来不是一个强力解决方案。要开始,使用蛮力来生成系列的第一项可能会给出关于数学公式的线索,或者手动执行第一步可能会给出关于动态编程方法的线索。 –