原题请见:http://segmentfault.com/q/1010000002627415
我的答案是用简短的递归来解,后来有空想了想传统 DP 的解法,发现也不难。推导过程如下:
S[0] = 0
S[1] = 1
S[2] = 1,1 | 2
S[3] = 1,2 | 1,1,1 | 2,1 | 3
S[4] = 1,3 | 1,1,2 | 2,2 | 1,2,1 | 1,1,1,1 | 2,1,1 | 3,1 |
^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
S[1] + "3" S[2] + "2" S[3] + "1"
...
S[n] = S[n-3] + S[n-2] + S[n-1]
^^^^^^ ^^^^^^ ^^^^^^
S + "3" S + "2" S + "1"
公式一出,DP 再无难点。直接根据公式建表,然后返回表尾即可。
cpp
std::vector<std::string> step(int n) { if (n < 1) return std::vector<std::string>{}; std::vector<std::vector<std::string>> cache( n > 3 ? n+1 : 4); cache[1] = {"1m"}; cache[2] = {"1m,1m", "2m"}; cache[3] = {"1m,2m", "1m,1m,1m", "2m,1m", "3m"}; for (int i = 4; i <= n; ++i) { for (const auto& s: cache[i-3]) cache[i].push_back(s + ",3m"); for (const auto& s: cache[i-2]) cache[i].push_back(s + ",2m"); for (const auto& s: cache[i-1]) cache[i].push_back(s + ",1m"); } return cache[n]; } int main() { for (const auto& s : step(4)) std::cout << s << std::endl; }
注意:这道题限制要求输出全部结果,这直接导致无论如何优化也只能是指数级的复杂度。故,说 DP 是不严谨的,只是往 DP 的思路上靠罢了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。