其他
算法:走N步
The following article is from 小K算法 Author 小K算法
01故事起源
02分析
走一步,只有3种路线。
走第二步要从前一步能到达的位置出发,所以总共就有7种方式。
可以发现,每一步能走的地方其实与上一步有关。每次走一步,要保证不走回头路,也就是不走上一步走过的地方就行了。
第i-1步向东走,那么第i步只能向北、向东。
第i-1步向西走,那么第i步只能向北、向西。
第i-1步向北走,那么第i步可以向北,向东,向西。
03算法建模一维的f[i]只能记录一个总数,而不能记录状态,所以要再多一维记录每一步走的方向。
设f[i][0],f[i][1],f[i][2]分别表示:第i步向东、向西、向北走的不同路线总数。
则有如下递推关系:
第i步向东,等于上一步向东和向北之和,即f[i][0] = f[i - 1][0] + f[i - 1][2]
第i步向西,等于上一步向西和向北之和,即f[i][1] = f[i - 1][1] + f[i - 1][2]
第i步向北,等于上一步向东,向西,向北之和,即f[i][2] = f[i - 1][0] + f[i - 1][1] + f[i - 1][2];
则走n步的总数即为f[n][0]+f[n][1]+f[n][2]。
f[0][0] = 1;
f[0][1] = 1;
f[0][2] = 1;
for (int i = 1; i < n; ++i) {
f[i][0] = f[i - 1][0] + f[i - 1][2];
f[i][1] = f[i - 1][1] + f[i - 1][2];
f[i][2] = f[i - 1][0] + f[i - 1][1] + f[i - 1][2];
}
cout << f[n - 1][0] + f[n - 1][1] + f[n - 1][2] << endl;
04优化
而f[i-1][2]=f[i-2][0]+f[i-2][1]+f[i-2][2]=s[i-2]。 得s[i]=2*s[i-1]+s[i-2]。 所以对公式变形,也可以通过一维完成递推。
s[0] = 1;
s[1] = 3;
for (int i = 2; i < n; ++i) {
s[i] = 2 * s[i - 1] + s[i - 2];
}
cout << s[n - 1] << endl;
05总结
推荐阅读:
每日打卡赢积分兑换书籍入口