马拦过河卒

声明:本人的水平。。。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;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值