• LFYZ-OJ ID: 1020 过河卒(NOIP2002)


    过河卒

    Proble Description

    如图,A 点有一个过河卒,需要走到目标 B 点。卒行走规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如上图 C 点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C)。卒不能通过对方马的控制点。

    棋盘用坐标表示,A 点(0,0)、B 点(n,m)(n, m 为不超过 20 的整数,并由键盘输入),同样马的位置坐标是需要给出的(约定: C不等于A,同时C不等于B)。现在要求你计算出卒从 A 点能够到达 B 点的路径的条数。1<=n,m<=15

    INPUT

    B点的坐标(n,m)以及对方马的坐标(X,Y){不用判错}

    OUTPUT

    一个整数(路径的条数)

    Sample Input

    6 6 3 2

    Sample Output

    17

    分析

    到达棋盘上的任意一点只有两条路:从上方,从左方。因此到达(n, m)点的路径数R(n, m)=R(n-1, m)+R(n, m-1),这就成了一个递推问题,递推的起点就是A点(0, 0)。整理一下,已知条件和递推规则如下:

    • 第0行,R(0, m)=R(0, m-1)
    • 第0列,R(n, 0)=R(n-1, 0)
    • 马可控点,R(n, m)=0
    • 其它,R(n, m)=R(n-1, m)+R(n, m-1)
    • 已知条件:R(0, 0)=1

    这样,可把棋盘用一个二维数组来表示。一行一行扫描数组的每个元素进行计算,最终可推算出R(n, m)

    代码示例

    #include<iostream>
    using namespace std;
    int M[20][20];									//棋盘 
    int main(){
    	int n, m, X, Y; 
    	scanf("%d%d%d%d", &n, &m, &X, &Y);
    	for(int i=0; i<=n; i++)						//A点到B点之间的节点全部初始化为-1 
    		for(int j=0; j<=m; j++)
    			M[i][j]=-1;
    												//马可控制点设置为0条路径 
    	M[X][Y]=M[X-2][Y-1]=M[X-2][Y+1]=M[X-1][Y-2]=M[X-1][Y+2]=
    			M[X+2][Y-1]=M[X+2][Y+1]=M[X+1][Y-2]=M[X+1][Y+2]=0;
    	M[0][0]=1;									//递推起点 
    	for(int i=0; i<=n; i++)
    		for(int j=0; j<=m; j++){
    			if(i==0 && j==0) 		continue;	//起点跳过 
    			if(M[i][j]==0)			continue;	//马可控点跳过 
    			if(i==0)		M[i][j]=M[i][j-1];
    			else if(j==0)	M[i][j]=M[i-1][j];
    			else  M[i][j]=M[i-1][j]+M[i][j-1];
    		}
    	printf("%d", M[n][m]);
    } 
    
  • 相关阅读:
    netbeans 打开项目时没有出现咖啡哪个标记
    java swing客户端程序调试的一些方式
    java客户端布局 GroupLayout 控件、按钮等布局
    ActiveMQ 增加消息 消费消息
    HBase学习解析之起源.md
    Hadoop学习解析之资源管理调度框架YARN
    Hive学习解析之工作原理.md
    Hive学习解析之系统架构.md
    js实现ajax获取的文件base64字符串处理.md
    springboot2.x整合quartz2.x.md
  • 原文地址:https://www.cnblogs.com/lfyzoi/p/6876065.html
Copyright © 2020-2023  润新知