【洛谷】P1002 过河卒

题目链接

题目描述

棋盘上 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  
View Code
原文地址:https://www.cnblogs.com/wangzhebufangqi/p/12796208.html