题目描述
棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示, A 点 (0, 0) 、 B点 (n, m)( n , m 为不超过 20 的整数),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 A 点能够到达 B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入输出格式
输入格式:
一行四个数据,分别表示 B 点坐标和马的坐标。
输出格式:
一个数据,表示所有的路径条数。
输入输出样例
输入样例#1:
6 6 3 3
输出样例#1:
6
说明
结果可能很大!
用dp[i][j]表示卒从起点走到 (i,j) 点所有可行的路径总数,所以dp[0][0]=1。卒行走的规则:可以向下、或者向右,所以状态转移方程是dp[i][j]=dp[i-1][j]+dp[i][j-1],同时,卒不能经过对方马的控制点。注意需要判断马的控制点是否出界。由说明可知数据类型用int可能存不了,用long long。
AC代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<iomanip> 5 #include<vector> 6 #include<stack> 7 using namespace std; 8 long long dp[21][21];//走到坐标为[i][j]的路径条数 9 bool cb[21][21];//棋盘上是否是控制点 //chessboard 10 int dx[8]={-2,-1,1,2,-2,-1,1,2},dy[8]={1,2,2,1,-1,-2,-2,-1}; //马走日字的八个方向 11 int main() 12 { 13 memset(dp,0,sizeof(dp)); 14 memset(cb,0,sizeof(cb)); 15 int p,q,n,m; 16 cin>>n>>m>>p>>q; 17 for(int i=0;i<8;i++) 18 { 19 int x=p+dx[i],y=q+dy[i]; 20 if(x>=0&&x<=n&&y>=0&&y<=m)//注意判断是否在边界内 21 cb[x][y]=1;//是控制点 22 } 23 cb[p][q]=1; 24 dp[0][0]=1;//在起点只有一条路 25 for(int i=1;i<=n;i++) 26 { 27 //第一列只能由上一行向下走,被控制点挡住则不通 28 if(cb[i][0]) dp[i][0]=0; 29 else dp[i][0]=dp[i-1][0]; 30 } 31 for(int j=1;j<=m;j++) 32 { 33 //第一行只能由前一列向右走,被控制点挡住则不通 34 if(cb[0][j]) dp[0][j]=0; 35 else dp[0][j]=dp[0][j-1]; 36 } 37 for(int i=1;i<=n;i++) 38 { 39 for(int j=1;j<=m;j++) 40 { 41 if(cb[i][j]) dp[i][j]=0;//到不了,到该点的路径数是0 42 else dp[i][j]=dp[i][j-1]+dp[i-1][j];//上一点向下走的路径数加上前一点向右走的路径数 43 } 44 } 45 cout<<dp[n][m];//输出结果 46 } 47