【题目描述】
棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。
【输入】
给出n、m和C点的坐标。
【输出】
从A点能够到达B点的路径的条数。
【输入样例】
8 6 0 4
【输出样例】
1617
【解题思路】
定义一个二维数组f[25][25],使用双层for循环遍历该数组,数组里的各个元素的值表示卒走到当前点的步数。
首先映射出马的所有控制点,例如p1点,马跳到p1点需在x坐标上向前移动两格,在y坐标上向前移动一格,所以mx[1] = 2,my[1] = 1,p1点坐标为(x+mx[1],y+my[1]);再如p5点,马跳到p5点需在x坐标上后退两格,在y坐标上后退一格,所以mx[5] = -2,my[5] = -1,p5点的坐标为(x+mx[5],y+my[5])。
将所有马的控制点算出来后,用judg函数判断马的所有控制点是否越界。若不越界,用二维数组g[25][25]保存马的控制点,遍历棋盘上每一个点,当这个点为马的控制点时,规定到这个点的所需步数为0,即f[i][j] = 0。由于卒只能向下或向右走,因此卒走到当前遍历的点只能从上方的格子或左侧的格子来,走到当前点所需步数即为走到上一格的步数加上走到左侧那一格的步数,故递推式为:a[i][j] = a[i-1][j] + a[i][j-1]。
【题解代码】
#include <bits/stdc++.h>
using namespace std;
int mx[10]={0,2,1,-1,-2,-2,-1,1,2},my[10]={0,1,2,2,1,-1,-2,-2,-1};
bool judge(int atemp,int btemp,int n,int m){
if (atemp>=0 && atemp<=n && btemp>=0 && btemp<=m) return true;
return false;
}
long long g[25][25]={0},f[25][25]={0};//涉及到累加数据范围可能会越界,所以用long long类型
int main(){
int x,y,n,m,atemp,btemp;
cin >> n >> m >> x >> y;
g[x][y] = 1; //马所在的点也为马的控制点,需标记出来
for (int i=1;i<=8;i++){
atemp = x+mx[i];
btemp = y+my[i];
if (judge(atemp,btemp,n,m)) g[atemp][btemp] = 1; //将马的控制点标记出来
}
f[0][0] = 1-g[0][0]; //若起点为马的控制点,则所需步数为0,不是马的控制点则为1
for (int i=0;i<=n;i++){
for (int j=0;j<=m;j++){
if (g[i][j] == 1) continue; //遇到马的控制点便跳过
if (i != 0) f[i][j] += f[i-1][j];
if (j != 0) f[i][j] += f[i][j-1];
}
}cout << f[n][m];
return 0;
}
标签:1314,Noip2002,int,mx,3.6,控制点,坐标,my,步数
From: https://blog.csdn.net/m0_66498724/article/details/132511077