马拦过河卒(三种做法)

马拦过河卒

Time Limit: 3000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。棋盘用坐标表示,A点(0,0)、B点(n,m)(n,m为不超过15的整数),同样马的位置坐标是需要给出的。现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

Input

一行四个数据,用空格分隔,分别表示B点的坐标和马的坐标。

Output

一个数据,表示所有的路径条数。

Sample Input

6 6 3 3

Sample Output

6

Hint

Source

代码实现:

 这是我一开始做这道题时的代码:c语言代码,从书上看的基本上是照着打的,当时也不十分的理解

#include<stdio.h>
int main()
{
    int dx[9]={0,-2,-1,1,2,2,1,-1,-2};
    int dy[9]={0,1,2,2,1,-1,-2,-2,-1};
    int m ,  n , x, y,i , j ;
    long long int f[20][20]={0};
    int g[20][20]={0};
    scanf("%d %d %d %d",&n,&m,&x,&y);
    g[x][y]=1;
    for(i=1;i<=8;i++)
        if(x+dx[i]>=0&&x+dx[i]<=n&&y+dy[i]>=0&&y+dy[i]<=m)
                g[x+dx[i]][y+dy[i]]=1;
        for(i=1;i<=n;i++)
        {
            if(g[i][0]!=1)
                f[i][0]=1;
            else
            for(;i<=n;i++)
            {
                f[i][0]=0;
            }
        }
        for(j=1;j<=m;j++)
        {
            if(g[0][j]!=1)
                f[0][j]=1;
            else
            for(;j<=m;j++)
                f[0][j]=0;
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(g[i][j]==1)
                f[i][j]=0;
                else
                f[i][j]=f[i-1][j]+f[i][j-1];
            }
        }
        printf("%lld\n",f[n][m]);
        return 0;
}


/***************************************************
****************************************************/

下面是我后来再一次做这道题脱离了课本,自己理解着写出来的,当然是上面的代码给于的思想 代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>


int main()
{
    int n , m , x , y ;
    int ma[9][2] ={0,0,1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1} ;//马可以走的地方
    int f[20][20] ; //用于记录路径
    int g[20][20] ; // 用于判断马的位置

    scanf("%d %d %d %d",&n,&m,&x,&y) ; //输入数据

    //初始化
    memset(f,0,sizeof(f))  ;
    memset(g,0,sizeof(g))  ;

    for(int i = 0 ; i<9 ; i++ )
    {
        int dx , dy  ;
        dx = x+ma[i][0] ;
        dy = y + ma[i][1] ;
        //防越界
        if(dx<0||dx>n||dy<0||dy>m)
            continue ;
        else g[dx][dy] = 1 ; //马的控制点
    }
    //第一列初始化
    for(int i=1 ; i <= n ; i++)
    {
        if(!g[i][0])
        f[i][0] = 1 ;
        else
            break ;

    }
    //第一行初始化
    for(int i = 1 ; i<= m ;i++)
    {
        if(!g[0][i])
            f[0][i] =1 ;
        else
            break;
    }
    //动态规划求路径
    for(int i=1 ; i<=n ; i++)
    {
        for(int j = 1 ;j<=m;j++)
            //如果遇到马的控制点说明,此路不通,f[i][j]为0
            if(g[i][j]==1)
            f[i][j] = 0 ;
        //经分析可知到达f[i][j]的路径等于从上面的路径和从右面的路径之和
        else
            f[i][j] = f[i-1][j] + f[i][j-1] ;
    }
    printf("%d\n",f[n][m]) ;
    return 0 ;
}


/***************************************************
f[i][j]的取值如下:
0       1       1       1       1       1       1
1       2       0       1       0       1       2
1       0       0       1       1       0       2
1       1       1       0       1       1       3
1       0       1       1       2       0       3
1       1       0       1       0       0       3
1       2       2       3       3       3       6
f[i][j]的数值代表是到达该点的路径。
****************************************************/

现在对这道题的理解

现在学了DFS算法,决定用DFS算法再重新做一遍

代码如下:

#include<bits/stdc++.h>

using namespace std;

int mmp[100][100] ;//棋盘
int vis[100][100] ; //标记变量
int step  = 0 ; //记录路径数
int a ,b ,n , m ;
int next1[9][2]={0,0,-2,1,2,1,-2,-1,2,-1,1,2,1,-2,-1,-2,-1,2}; //马的走动方式

void dfs(int x , int y)
{
    int i ;
    int next[2][2] = {{0,1},{1,0}} ; //卒的走动方式,卒无法向上走,也无法向右走
    int tx ,ty ;
    if(x==n&&y==m)
        step++ ;
    for(i=0;i<2;i++)
    {
        tx = x + next[i][1] ;
        ty = y + next[i][0] ;
        if(tx<0 || tx>n || ty < 0 || ty > m)
            continue ;
        if(!vis[tx][ty]&&mmp[tx][ty])
        {
            vis[tx][ty] = 1 ;
            dfs(tx,ty)  ;
            vis[tx][ty] = 0 ;
        }

    }
}

int main()
{
    int i ;
    cin>>n>>m>>a>>b ; //a,b是马的坐标。
    memset(vis,0,sizeof(vis)) ;
    memset(mmp,1,sizeof(mmp)) ; //先假设棋盘上没有马
    for(i=0;i<=8;i++)
    {
        if(a+next1[i][0]>=0&&a+next1[i][0]<=n&&b+next1[i][1]>=0&&b+next1[i][1]<=m)
        {
            mmp[a+next1[i][0]][b+next1[i][1]] = 0 ; //马的阻挡,卒无法通过。
        }
    }
    vis[0][0] = 1 ;
    dfs(0,0) ;
    cout<<step<<endl ;
    return 0 ;
}

/*************************************
**************************************/


c语言版如下: 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int mmp[20][20] ;
int vis[20][20] ;
int step ;
int ma[9][2] ={0,0,1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1} ;
int n  , m ;
int b , c ;

void dfs(int x , int y)
{
    if(x ==n&&y==m)
        step++ ;
    int next[2][2] = {1,0,0,1} ;
    int  i  ;
    int dx , dy ;
    for(i= 0 ; i<2 ;i++)
    {
        dx = x + next[i][1] ;
        dy = y + next[i][0] ;
        if(dx<0||dx>n||dy<0||dy>m)
            continue ;
        if(!vis[dx][dy]&&mmp[dx][dy]==0)
        {
            vis[dx][dy] = 1 ;
            dfs(dx,dy) ;
            vis[dx][dy] = 0 ;
        }
    }
}

int main()
{
    int i ;
    int dx , dy ;
    scanf("%d %d %d %d",&n,&m,&b,&c) ;
    memset(vis,0,sizeof(vis)) ;
    memset(mmp,0,sizeof(mmp)) ;
    for(i = 0 ; i<= 8 ; i++)
    {
        dx = b + ma[i][0] ;
        dy =  c + ma[i][1] ;
        if(dx<0||dx>n||dy<0||dy>m)
            continue ;
        else
            mmp[dx][dy] = 1 ;;
    }
    vis[0][0] = 1 ;
    dfs(0,0) ;
    printf("%d\n",step) ;
    return 0 ;
}


/***************************************************
****************************************************/

  • 18
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值