解题思路:
马的移动路线为向右或者向下,那么以后的每一步都只能由这两个方向而来,满足最优子结构,有些点是不能走的,所以要根据状态来设置转移方程,最后做出决策
1.分析题意,每一步卒的路线都只能向下走或者向右走,那么其实第0行和第0列的方案数均为1,因为只能通过左边或者上边过来,在这个时候需要初始化,因为马的控制点如果是在第0行或者第0列的话该点右面或者下面方案数均为0!
2.然后设置马的方向数组,xx和yy,分别有9个点不能过
3.接下来枚举第1行第1列到终点,如果该点不是马的 控制点的话,其方案数应该为正左边和正上方的方案数之和,状态转移方程为dp[i][j]=dp[i-1][j]+dp[i][j-1]
4.最后输出终点方案数即可
#include<bits/stdc++.h>
using namespace std;
long long dp[30][30];
int x,y,x2,y2;
int xx[10]={0,-2,-1,1,2,2,1,-1,-2};//马的方向数组
int yy[10]={0,1,2,2,1,-1,-2,-2,-1};
bool check(int a,int b)//检查该位置是否为马控制点
{
for(int i=0;i<=8;i++)
{
if(x2+xx[i]>=0&&y2+yy[i]>=0&&x2+xx[i]<=x&&y2+yy[i]<=y)//如果没有越界的话
{
if(x2+xx[i]==a&&y2+yy[i]==b)//如果该点是马的控制点
return false;//返回错误
}
}
return true;
}
int main()
{
cin>>x>>y>>x2>>y2;//输入B点坐标和马的坐标
if(x2==0&&y2==0)//如果起点就是马的控制点,方案为0
{
cout<<0;
return 0;
}
dp[0][0]=1;//将起点设置为1
for(int i=1;i<=y;i++)//计算第0行的方案数
if(check(0,i)==1)//如果该点不是马的控制点
dp[0][i]=dp[0][i-1];//方案数为左边的方案数
for(int i=1;i<=x;i++)//计算第0列的方案数
if(check(i,0)==1)//如果该点不是马的控制点
dp[i][0]=dp[i-1][0];//方案数为上边的方案数
for(int i=1;i<=x;i++)//枚举每行
{
for(int j=1;j<=y;j++)//枚举每列
{
if(check(i,j)==1)//如果该点不是马的控制点
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];//方案数为正上方和正左方方案数之和
}
}
}
cout<<dp[x][y];
return 0;
}