我发现动态规划这类问题有一个特点:”大问题依赖于某些小问题“。我倒觉得这种思想对于处理一些比较大的,一眼较难看出的问题比较合适的方式,但是通过分析之后,发现可以将大问题归结为小问题的解决,这些小问题环环相扣,直到问题被完全分解。
· 1个问题:台阶问题,有个人正在上楼梯,楼梯有N个台阶,他可以一次性上1阶,2阶级,3阶级,那么计算他有多少种上楼梯的方式。
分析:我们来看,这种问题乍一看貌似没什么头绪,但是我们可以这么来,要上到第N阶,那么我的倒数第二次可以上到第(N-3),或者第(N-2),或者第(N-1)。因为只有在这三种方式下,我才能最后一次上到第N层。那么假设到达第N-3层有X1种走法,到达第N-2层有X2种走法,到达第N-1层有X3种走法,到达第N层有X种走法,那么:X = X1+X2+X3; 以此类推,我们可以得到如下代码:
#include <iostream>
#include <iso646.h>
#include <algorithm>
#include <functional>
__int64 Result(__int64 step) {
__int64 _dsum = 0;
if (step < 0) std::cout << "False" << std::endl;
if (step == 1) std::cout << "1" << std::endl;
if (step == 2) std::cout << "2" << std::endl;
if (step == 3) std::cout << "4" << std::endl;
if (step > 3) {
__int64 _d1 = 1;
__int64 _d2 = 2;
__int64 _d3 = 4;
for (size_t i = 4; i <= step; i++){
_dsum = _d1 + _d2 + _d3;
_d1 = _d2;
_d2 = _d3;
_d3 = _dsum;
}
}
return _dsum;
}
int main() {
__int64 M;
std::cin >> M;
std::cout << Result(M) << std::endl;
std::cin.get();
}
同样,以上的代码依然可能随着M的增大会爆栈。(就这个题目而言,貌似有些类似斐波那契数列)。你看,我们把N个台阶的问题,分成了N-1,N-2,N-3个台阶的问题,但是分成的这些子问题,彼此都是有联系的,不是独立的,都会对最终的结果产生影响。当然,也可以用递归来实现。这就是另外一回事了。