题目点我
好像是某一年微软编程之美的题目,其实有数学做法:令
F(n)
表示走n步的方法总数,则可以得到递推式
F(n)=F(n−1)+2∗∑k=1n−2F(k)
再变下型可以得到(根据1楼评论提示,thx)
F(n)=F(n−1)+F(n−2)+F(n−2)+2∗∑k=1n−3F(k)
=F(n−1)+F(n−2)+F(n−1)=2∗F(n−1)+F(n−2)
以及两个边界条件
F(1)=3,F(2)=7
每次考虑上一步方向是向北走的情况,从接下来这一步开始又成为了完全相同的计数问题,因为往三个方向都可以走。
如果第一步向北走,接下来 n−1 步走法数显然是 F(n−1) 。
如果第一步向东/西走,第二步向北走,接下来 n−2 步走法数是 F(n−2) ,东西对称要乘以二。
如果第三步向北走,接下来 n−3 步走法数是 F(n−3) 。以此类推。
然而由于博主智商不发达,上来就写了个搜索的做法,也20ms水过了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxn 25
const int nStartX = maxn, nStartY = 0;
bool bMap[maxn + maxn][maxn]; //x, y
int nAns, nDir[3][2] = {{0, 1}, {-1, 0}, {1, 0}};
void dfs(int nX, int nY, int nStepLeft){
if(nStepLeft == 0){
nAns++;
return;
}
int nNextX, nNextY;
for(int i = 0; i < 3; i++){
nNextX = nX + nDir[i][0];
nNextY = nY + nDir[i][1];
if(bMap[nNextX][nNextY] == false){
bMap[nNextX][nNextY] = true;
dfs(nNextX, nNextY, nStepLeft - 1);
bMap[nNextX][nNextY] = false;
}
}
return;
}
int main(){
int nSteps;
while(scanf("%d", &nSteps) != EOF){
nAns = 0;
memset(bMap, false, sizeof(bMap));
bMap[nStartX][nStartY] = true;
dfs(nStartX, nStartY, nSteps);
printf("%d\n", nAns);
}
return 0;
}