过河卒【递推】

> Description
如图,A 点有一个过河卒,需要走到目标 B 点。卒行走规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如上图 C 点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C)。卒不能通过对方马的控制点。
过河卒【递推】_第1张图片
棋盘用坐标表示,A 点(0,0)、B 点(n,m)(n,m 为不超过 20 的整数,并由键盘输入),同样马的位置坐标是需要给出的(约定: C<>A,同时C<>B)。现在要求你计算出卒从 A 点能够到达 B 点的路径的条数。


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


> Output
一个整数(路径的条数)。


> Sample Input
6 6 3 2


> Sample Output
17


> 解题思路
自我感觉这一道题跟骑士游历有点像,而且比那一道题要简单一点,因为这一道题的卒只能往右走或往下走,就不用再存进一个数组了。
其实也可以说这个卒只能上面走下来或从左边走过来,所以位置(i,j)的数就等于它上面的数加上它左边的数,然后马和马的控制点就设为0。边界设为1(马和马后面所以的数都设为0),如下图:
过河卒【递推】_第2张图片
后面都是这样一直加过去(电脑与本人的字有很大的差异)


> 代码

#include<iostream>
#include<cstdio>
using namespace std;
const int x1[9]={0,-2,-1,1,2,2,1,-1,-2};
const int y1[9]={0,1,2,2,1,-1,-2,-2,-1};
long long s[25][25]={0},a[25][25]={0};
int n,m,x,y;

int main()
{
	scanf("%d%d%d%d",&n,&m,&x,&y);
	memset(a,0,sizeof(a));
	a[x][y]=1;
	for(int i=1;i<=8;i++)
	 if(x+x1[i]>=0&&y+y1[i]>=0) 
	   a[x+x1[i]][y+y1[i]]=1;
	//a数组用来标记马的位置,马和马的控制点设为1
	
    s[0][0]=1;
    for(int i=1;i<=n;i++) 
    {
    	if(a[i][0]==0) s[i][0]=1;
    	else break;//如果边界有马,后面的就都为0
    } //行
     for(int j=1;j<=m;j++) 
     {
     	if(a[0][j]==0) s[0][j]=1;
     	else break;
     } //列
     //设置边界的初值
     
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
     {
     	if(a[i][j]==0) 
     	  s[i][j]=s[i-1][j]+s[i][j-1];
     	 //位置没有马就继续累加
     	else s[i][j]=0;
     }
    printf("%I64d",s[n][m]);
	return 0;
}

你可能感兴趣的:(过河卒【递推】)