前言
这是我的第一篇题解,也是一个新的阶段的开始~苯人入门不久,如有错误请多指正。
题目描述
棋盘上 A A A 点有一个过河卒,需要走到目标 B B B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C C C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示, A A A 点 ( 0 , 0 ) (0, 0) (0,0)、 B B B 点 ( n , m ) (n, m) (n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 A A A 点能够到达 B B B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式
一行四个正整数,分别表示 B B B 点坐标和马的坐标。
输出格式
一个整数,表示所有的路径条数。
样例 #1
样例输入 #1
6 6 3 3
样例输出 #1
6
提示
对于 100 % 100 \% 100% 的数据, 1 ≤ n , m ≤ 20 1 \le n, m \le 20 1≤n,m≤20, 0 ≤ 0 \le 0≤ 马的坐标 ≤ 20 \le 20 ≤20。
【题目来源】
NOIP 2002 普及组第四题
代码实现
#include <bits/stdc++.h>
using namespace std;
bool vis[25][25];
long long res[25][25];
int main ()
{
res[1][1]=1;
int n,m,x,y;
cin>>n>>m>>x>>y;
n++;
m++;
x++;
y++;
//标记马占领的位置
vis[x][y]=1;
vis[x-2][y-1]=1;
vis[x-2][y+1]=1;
vis[x+2][y-1]=1;
vis[x+2][y+1]=1;
vis[x-1][y+2]=1;
vis[x-1][y-2]=1;
vis[x+1][y-2]=1;
vis[x+1][y+2]=1;
//dp
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
if (i==1&&j==1) continue;
else if (!vis[i][j])
{
res[i][j]=res[i][j-1]+res[i-1][j];
}
}
}
cout<<res[n][m]<<endl;
return 0;
}
题目分析
该题为动态规划入门题,主要解题思路和爬楼梯类似。该题有三个关键点:
- 由于卒只有向下、向右两种移动方式,故递推公式为 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] dp[i][j]=dp[i-1][j]+dp[i][j-1] dp[i][j]=dp[i−1][j]+dp[i][j−1]。
- 马按“日”字移动,不熟悉象棋的同学可能误以为马的控制范围是正方形(误
- 要注意最终结果的范围,输入20 20 10 10测试时,若所开 r e s res res数组为int类型,得到结果为负数;故 r e s res res数组应为long long类型。