这是一道比较简单的dp问题,根据题意进行模拟就可以了。有两个需要注意的点:
- 转移方程为:dp[i][j]=dp[i-1][j]+dp[i][j-1]。
- 棋盘起点为(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;
}