题解 P1002 【过河卒】

kradcigam

2019-01-30 14:40:11

Solution

# 正文 ![](https://cdn.luogu.com.cn/upload/image_hosting/dqlo9i4w.png) 简单描述一下题意: 士兵想要过河,他每一次可以往下走一格,也可以往右走一格,但马一步走到的地方是不能走的,问走到$n$行,$m$列有多少种走法 我们显然应该先根据马的位置将不能走的格子做一下标记 于是,就会写下这段代码: ```cpp void work(long long x,long long y){ ma[x][y]=1; ma[x-1][y-2]=1; ma[x-2][y-1]=1; ma[x-2][y+1]=1; ma[x-1][y+2]=1; ma[x+1][y-2]=1; ma[x+2][y-1]=1; ma[x+2][y+1]=1; ma[x+1][y+2]=1; } ``` 之后就可以使用奥数中的一种简单而常用的方法——**标数法** **可以举个例子**: ![123.png](https://i.loli.net/2019/10/25/OlK3HhBWmTRqguf.png) 从这个表格的第一行第一列,走到第二行第二列的走法数量是由走到第一行第二列的方案数+第二行第一列的方案数 也就是走到x行,y列的方案数=走到x-1行,y列的方案数+走到x行,y-1列的方案数(出界就按0算) 也就是 $$f[i][j]=f[i-1][j]+f[i][j-1]$$ 因为走到$x$行$y$列的方案显然是来自于它的左边和它的上面,因为只有这两个格子才可以一步到达这个格子。 于是我们就可以开始递推: ```cpp for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(i==1&&j==1)continue; if(ma[i][j]==0)x[i][j]=x[i-1][j]+x[i][j-1]; } } ``` 下面是我AC的代码 ```cpp #include <bits/stdc++.h> using namespace std; long long a,b,n,m,x[23][23],ma[23][23]; void work(long long x,long long y){ ma[x][y]=1; ma[x-1][y-2]=1; ma[x-2][y-1]=1; ma[x-2][y+1]=1; ma[x-1][y+2]=1; ma[x+1][y-2]=1; ma[x+2][y-1]=1; ma[x+2][y+1]=1; ma[x+1][y+2]=1; } int main(){ scanf("%lld %lld %lld %lld",&n,&m,&a,&b); a++; b++; n++; m++; work(a,b); x[1][1]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(i==1&&j==1)continue; if(ma[i][j]==0)x[i][j]=x[i-1][j]+x[i][j-1]; } } printf("%lld",x[n][m]); return 0; } ``` # 后记与补充 ![123.png](https://i.loli.net/2019/10/25/OlK3HhBWmTRqguf.png) 观看这张图,我们还可以发现其他的东西,我们能发现下面一行比上一行大的值,就是它左边格子的值,所以,我们可以将这道题优化成一维,代码实现也是很简单的。 $$f[i]+=f[i-1]$$ ```cpp #include <bits/stdc++.h> using namespace std; long long a,b,n,m,f[23],ma[23][23]; void work(long long x,long long y){ ma[x][y]=1; ma[x-1][y-2]=1; ma[x-2][y-1]=1; ma[x-2][y+1]=1; ma[x-1][y+2]=1; ma[x+1][y-2]=1; ma[x+2][y-1]=1; ma[x+2][y+1]=1; ma[x+1][y+2]=1; } int main(){ scanf("%lld %lld %lld %lld",&n,&m,&a,&b); a++; b++; n++; m++; work(a,b); x[1][1]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(i==1&&j==1)continue; if(ma[i][j]==0)f[j]+=f[j-1]; } printf("%lld",f[m]); return 0; } ``` 如果我的文章对你有帮助请点个赞!!! 谢谢。