这是一道比较简单的dp问题,根据题意进行模拟就可以了。有两个需要注意的点:

  1. 转移方程为:dp[i][j]=dp[i-1][j]+dp[i][j-1]。
  2. 棋盘起点为(0,0),为了防止数组越界,需要将棋盘起点转移至(1,1)。

具体解决方法和思路在代码注释中都要详细讲解,希望大家可以认真看。
参考代码如下:

#include<iostream>
#include<cstring>
using namespace std;
bool vis[23][23];
//确定方向
int dirx[8]={1,2,1,2,-1,-2,-1,-2};
int diry[8]={2,1,-2,-1,2,1,-2,-1};

long long int dp[23][23];//用来记录到达每个点的最小步数(In order to record the least numbers we can get !)
int main()//棋盘从(0,0)点开始
{
    ios::sync_with_stdio(false);
    memset(vis,true,sizeof(vis));
    int n,m,x,y;
    cin>>n>>m>>x>>y;
    x+=1,y+=1,n+=1,m+=1;//棋盘设置成从(1,1)点开始
    vis[x][y]=false;//将马所在的点设置为不可通过的点
    //将马的控制点设置为不可通过的点
    for(int i=0;i<8;i++)
    {
        int dx=x+dirx[i];
        int dy=y+diry[i];
        if(dx>=0&&dx<=n&&dy>=0&&dy<=m)
        vis[dx][dy]=false;
    }
    for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
          {
              if(i==1&&j==1)
              {
                  dp[1][1]=1;
                  continue;
              }
              if(!vis[i][j])//如果该点是不可通过的点
              {
                  dp[i][j]=0;
                  continue;
              }
              dp[i][j]=dp[i-1][j]+dp[i][j-1];
          }
    
    /*for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
       {
            cout<<dp[i][j]<<" ";
       }
       cout<<endl;
    }
    cout<<endl<<endl<<endl;
    
   
    for(int i=1;i<=n;i++)//输出棋盘中哪些是不可通过的点
    {
        for(int j=1;j<=m;j++)
       {
            if(vis[i][j])
            cout<<0<<" ";
            else
            cout<<1<<" ";
       }
       cout<<endl;
    }
    */
       
          
    cout<<dp[n][m]<<endl;
    return 0;
}