算法与数据结构---过河卒-搜索(递归)写法常见易错点

算法与数据结构---过河卒-搜索(递归)写法常见易错点

一、总结

一句话总结:

f[i][j]=f[i-1][j]+f[i][j-1]这样的递推表达式,取数之前一定要保证数是存在的

1、表示马的控制点如何表示?

int hx[9]={0,-2,-1,1,2,2,1,-1,-2};
int hy[9]={0,1,2,2,1,-1,-2,-2,-1};

2、边界条件不清晰易出错?

A、横轴f[i][0]=1(1<=i<=bx)和纵轴f[0][i]=1(1<=i<=by)是边界点,
B、f[i][by]和f[bx][i]并不是边界点
C、f[i][0]=1和f[0][i]=1做边界点会出错,因为当马的位置如果是(4,0),那么(5,0)的位置本来是去不了的,

3、递归一般是由终止条件到达初始条件,比如过河卒?

那么递归的关系式应该是f[i][j]=f[i-1][j]+f[i][j-1],而不是f[i][j]=f[i+1][j]+f[i][j+1]

4、这题(过河卒)的数据量是大于int的,所以定义缓存数组f的时候要用long long?

long long f[25][25];这题的数据量是大于int的,所以要用long long

5、这题(过河卒)的数据量是大于int的,所以递归函数的返回值要用long long,而不能是int?

int find(int x,int y){} 这样就是错的
//递归函数返回值的问题
int find(int x,int y){
    if(f[x][y]!=-1) return f[x][y];
    else{
        return f[x][y]=find(x-1,y)+find(x,y-1);
    }
}

6、如下初始化f[i][0]和f[0][i]会造成什么问题?

如果有马在中间,比如(4,0),4后面的点本来是达不到的,但是如下初始化之后,是可以达到的,这样就出错了

|||-begin

初始状态:
马控制的点为0
f[0][0]=0
f[i][0]=1 (1<=i<=bx)
f[0][i]=1 (1<=i<=by)
//初始化f数组
f[0][0]=0;
for(int i=1;i<=bx;i++) f[i][0]=1;
for(int i=1;i<=by;i++) f[0][i]=1;

|||-end

7、f[i][j]=f[i-1][j]+f[i][j-1]这样的递推表达式,无论是做递归,还是做递推,要注意什么?

要保证i和j大于等于1,小于1的情况要单独分析,取数之前一定要保证数是存在的

二、过河卒-递归写法常见易错点

博客对应课程的视频位置:

1、题目描述

 

题目位置

P1002 过河卒 - 洛谷
https://www.luogu.com.cn/problem/P1002

 

2、代码

 1 /*
 2 
 3 卒子可以向下走和向右走
 4 
 5 如果没有这个马,搜索应该怎么做
 6 
 7 递归:
 8 递归的终止条件:起点
 9 递归的递推表达式:卒子可以向下走和向右走
10 (f[i][j]=f[i-1][j]+f[i][j-1])
11 递归的返回值:路径条数
12 
13 
14 如果有马的情况
15 递归的终止条件:起点或者马控制的区域
16 
17 
18 A是A点 , B是B点, M是马的位置, X是被马拦着不能走的点
19 A 0 0 0 0 0 0
20 0 0 X 0 X 0 0
21 0 X 0 0 0 X 0
22 0 0 0 M 0 0 0
23 0 X 0 0 0 X 0
24 0 0 X 0 X 0 0
25 0 0 0 0 0 0 B
26 其中每个点的值代表的是当前这个点会有几条路径用过这个点
27 (路径指的是从A到B的路径)
28 
29 1 1 1 1 1 1 1
30 1 2 X 1 X 1 2
31 1 X 0 1 1 X 2
32 1 1 1 M 1 1 3
33 1 X 1 1 0 X 3
34 1 1 X 1 X 0 3
35 1 2 2 3 3 3 6
36 
37 
38 这里初始化的时候能直接初始化i=0和j=0对应的两条线么
39 不能,因为如果这样初始化后,当马的位置如果是(4,0),
40 那么(5,0)的位置本来是去不了的,
41 但是这样初始化却会初始化为1
42 
43 
44 */
45 #include <iostream>
46 #include <cstring>
47 using namespace std;
48 int hx[9]={0,-2,-1,1,2,2,1,-1,-2};
49 int hy[9]={0,1,2,2,1,-1,-2,-2,-1};
50 long long f[25][25];
51 //递归函数返回值的问题
52 long long find(int x,int y){
53     if(f[x][y]!=-1) return f[x][y];
54     else{
55         if(x-1>=0&&y-1>=0) return f[x][y]=find(x-1,y)+find(x,y-1);
56         else if(x-1>=0) return f[x][y]=find(x-1,y);
57         else if(y-1>=0) return f[x][y]=find(x,y-1);
58         else return 0;   
59     }
60 }
61 
62 int main(){
63     int bx,by,mx,my;
64     cin>>bx>>by>>mx>>my;
65     //初始化f数组
66     memset(f,-1,sizeof(f));
67     f[0][0]=1;
68     //将马控制得到的位置初始化到f数组
69     for(int i=0;i<=8;i++){
70         //马的位置没出界
71         int now_x=mx+hx[i];
72         int now_y=my+hy[i];
73         if(now_x>=0&&now_x<=bx&&now_y>=0&&now_y<=by){
74             f[now_x][now_y]=0; 
75         }
76     }
77 
78     cout<<find(bx,by)<<endl;
79     return 0;
80 }
 
原文地址:https://www.cnblogs.com/Renyi-Fan/p/13107411.html