P1002-过河卒
最后更新时间:
文章总字数:
预计阅读时间:
页面浏览: 加载中...
解法
这一题目前了解到有两种解法,递归和动态规划(DP算法)。
递归
一开始我想到的方法是递归,通过递归罗列出卒走路的所有路线,再将成功的次数加起来。
但是这个问题上,用递归所要经历的分支实在是太多了,不出意外地超时了。
所以后续尝试将备忘录的思想和递归结合,设置一个二维数组当做备忘录,将走到一个点的路线数记录下来,这样以后再遇到需要这个点的路线数的情况,就不用再递归了,直去备忘录取数字就行。这样可以用空间换时间。最后证实是可行的。
1 |
|
需要注意的是,存储路线数的变量一定要用long long类型,因为在第三个测试节点,路线数已经到了11位大小,超出了int和long(之前没考虑到这点,浪费了很多时间)。
DP算法
后面看了一下题目标签了解了一下DP算法,发现用dp确实简便了许多,递归还要套一层又一层,可能会栈溢出,DP算法只要一个双层循环就行了,方便了许多,以后遇到类似问题可以多一种思路。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int fx[] = {0, -2, -1, 1, 2, 2, 1, -1, -2};
const int fy[] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
//马可以走到的位置
int bx, by, mx, my;
ll f[40][40];
bool s[40][40]; //判断这个点有没有马拦住
int main(){
cin>>bx>>by>>mx>>my;
bx += 1; by += 1; mx += 1; my += 1;
//坐标+1以防越界
f[1][0] = 1;//初始化
s[mx][my] = 1;//标记马的位置
for(int i = 1; i <= 8; i++) s[mx + fx[i]][my + fy[i]] = 1;
for(int i = 1; i <= bx; i++){
for(int j = 1; j <= by; j++){
if(s[i][j]) continue; // 如果被马拦住就直接跳过
f[i][j] = f[i - 1][j] + f[i][j - 1];
//状态转移方程
}
}
cout<<f[bx][by]<<endl;
return 0;
}