过河卒p1002

题意: 从(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("\n");
  }

  cout<<f[n][m]<<endl;
}

 

posted on 2020-09-29 23:24  mmn  阅读(140)  评论(0编辑  收藏  举报