题意: 从(0,0)开始到(n,m)的路径有多少条,要判断其中一个马,及其周围的8个点不能动(马以日字走动)
思路:
1,递推方程:本节点的路径数=此节点上边的路径数+此节点左边的路径数,则方程 f[i][j]=f[i-1][j]+f[i][j-1];
2,递推方程有了之后,确定初始条件f[0][0]=1;为了不使数组越界,i=0,j=0时,只需要加一项即可;
3,设置一个标记数组,将马及其周围八个点进行标记一下;
注意点:
1,在对马进行标记时,要注意判断,不能使数组越界,数组越界会出现错误;
2,对递推数组进行累加时,对i,j不为0进行巧妙的处理;
3,对于已被标记的点使用f[i][j]*=!vis[i][j],这样对于已被标记的点则可以使f[i][j]=0;
反思:
看过好多题解,因为自己很菜,所以刚开始没有判断边界,昨天看这个题本以为很简单,但是今天一敲才知道各种小错误不断,做完这个题已经两个多小时了,感觉收获蛮多的,知道了判断边界,以及数组越界,
最终的这个代码,我觉得是看起来最顺眼的,因为下标直接从0开始+判断边界+处理数组越界问题很清晰,在题解中也看到很多其他的代码,有的避免了判断边界,而直接把坐标加2,这样有时候对i和j的判断会因为疏忽出现错误(蒟蒻是这个亚子),有的直接是加1,还有用搜索解决的,但是搜索的复杂度太高。
以后写代码时要考虑周全,坑点太多,做的题太少,容易踩坑,以后努力刷题啊;
代码:
#include<bits/stdc++.h> const int maxn=50; typedef long long ll; using namespace std; ll f[maxn][maxn]; bool vis[maxn][maxn]; int fx[]={0,-2,-2,-1,-1,1,1,2,2}; int fy[]={0,-1,1,2,-2,-2,2,-1,1}; int main() { int n,m,a,b; cin>>n>>m>>a>>b; vis[a][b]=1; for(int i=1; i<=8; i++) { int x=a+fx[i]; int y=b+fy[i]; if(x>=0&&x<=n&&y>=0&&y<=m)//判断边界,否则会数组越界出现错误 vis[x][y]=1; } f[0][0]=1; for(int i=0; i<=n; i++) { for(int j=0; j<=m; j++) { if(i) f[i][j]+=f[i-1][j]; if(j) f[i][j]+=f[i][j-1]; f[i][j]=f[i][j]*!vis[i][j];//标记的为0 } } for(int i=0; i<=n; i++) { for(int j=0; j<=m; j++) printf("%lld ", f[i][j]); printf(" "); } cout<<f[n][m]<<endl; }