声明:本人的水平。。。QAQ不提了,代码仅供参考。路过的巨巨们发现有不对头的地方,可以评论或者私信, 不胜感激。::>_<::
Problem Description
棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。棋盘用坐标表示,A点(0,0)、B点(n,m)(n,m为不超过15的整数),同样马的位置坐标是需要给出的。现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
Input
一行四个数据,用空格分隔,分别表示B点的坐标和马的坐标。
Output
一个数据,表示所有的路径条数。
Example Input
6 6 3 3
Example Output
6
Think: 马走“日”字, 代码实现起来就是对位置坐标X、Y,进行+-1、2操作。是马可以一步到达的点(包括一开始马的坐标)。分析可知从某个点到达终点B的路径条数是B点正上+左边两个点的路径条数和。比如从(1,1)到(2,2),根据题目里卒的行走规则有两条路径可走,1+1 = 2嘛。那么问题来了,从起始位置(0,0),到终点B的过程中如果遇到“马的控制点”怎么办?思考一下~肯定是从马的控制点出发的路径数为0了,因为相当于“出发点”不存在了。。。分析完了之后,就知道要开个两个二维数组,一个保存地图—标记马的控制点,再开个数组来保存每个点的路径数(要根据马的控制点初始化一下), 最后两个for循环,一步步递推模拟。
代码如下,纯C无添加
#include<stdio.h>
#include<string.h>
int f[20][20];
int g[20][20];
int main()
{
int i, j, n, m, x, y;
memset(f, 0, sizeof(f)); //清空,数组元素起始值皆为0
memset(g, 0, sizeof(g));
scanf("%d %d %d %d", &n, &m, &x, &y); //输入目标点B、马的位置
f[0][0] = 1; //思考一下为什么出发点的路径数为1,而不是为0
g[x][y] = 1; //自己偷偷举个小栗子就知道啦^_^
g[x - 1][y - 2] = 1; g[x - 1][y + 2] = 1; //马的控制点
g[x + 1][y + 2] = 1; g[x + 1][y - 2] = 1; //第一次做的时候
g[x - 2][y - 1] = 1; g[x - 2][y + 1] = 1; //1和2傻傻没看清楚
g[x + 2][y - 1] = 1; g[x + 2][y + 1] = 1; //WA了N次,呜呜~
for(i = 1; i <= n; i++){ //纵向边界初始化(第一列)
if(!g[i][0]){
f[i][0] = 1; //不是马的控制点,该点的路径数设为1
}
else{ //否则在边界上此点及之后的点路径数为0
break; //思考一下为什么?
} //在边界上还可以从哪里到该点?
} //是不是不能了,因为可以来的路被马“截断”了
for(i = 1; i <= m; i++){ //横向边界初始化(第一行)
if(!g[0][i]){ //同上,不解释
f[0][i] = 1;
}
else{
break;
}
} //一步步递推
for(i = 1; i <= n; i++){ //本题重要的代码精华部分,模拟从起始点出发,每
for(j = 1; j <= m; j++){ //一步到达的点的路径数之和
if(!g[i][j]) //如果不是马的控制点,该点的路径数为左边+上边点的路
f[i][j] = f[i - 1][j] + f[i][j - 1]; //径数
}
}
printf("%d\n", f[n][m]); //输出所有的路线和
return 0;
}