22.1.26 递归改动态规划
1.套路:
1)递归:根据题目写出递归版本;
2)记忆化搜索:用某种结构存储已经计算过的信息,省去重复计算的过程;
-
严格表结构的构造过程:
-
分析可变参数的范围(有几个可变参数就是几维表结构);
-
标出待求的终止位置;
-
根据不同的basecase标出不用通过计算就能得到答案的位置;
-
根据递归,找依赖关系,填表。
-
2.问题分析:
1)机器人走路问题:
-
描述:给出1~N,N个位置,给出最终需要到达的位置E,当前位置cur,剩余步数rest。
-
-
例如有1,2,3,4四个位置,机器人现在位于位置2,需要到达位置3,还剩3步,返回方案总数。
-
可执行的方案有:2->3->4->3,2->1->2->3,2->3->2->3 共计三种方案。
-
-
code(暴力递归版本):
public static int process(int N, int E, int rest, int cur)
{
if(rest == 0)
return cur == E ? 1 : 0;//判断方案是否可行的最终条件
if(cur == 1)//当前是一位置,只能往二位置走
process(N, E, rest - 1, 2);
if(cur == N)//当前来到N位置,只能向N-1位置走
process(N, E, rest - 1, N - 1);
return process(N, E, rest - 1, cur - 1)
+ process(N, E, rest - 1, cur + 1);//中间位置可以向两边走
}
public static void main(String[] args)
{
System.out.println(process(4, 3, 3, 2));
}
//结果输出 3
-
code(记忆化搜索版本)
public static int process(int N, int E, int rest, int cur, int[][] dp)
{
if(dp[rest][cur] != -1)
return dp[rest][cur];//不等于-1说明之前已经计算过,直接返回就行
if(rest == 0)
{
dp[rest][cur] = cur == E ? 1 : 0;
return dp[rest][cur];
}
if(cur == 1)
dp[rest][cur] = process(N, E, rest - 1, 2, dp);
else if(cur == N)
dp[rest][cur] = process(N, E, rest - 1, N - 1, dp);
else
dp[rest][cur] = process(N, E, rest - 1, cur - 1, dp)
+ process(N, E, rest - 1, cur + 1, dp);
return dp[rest][cur];
}
public static void walk1(int N, int E, int rest, int cur)
{
int[][] dp = new int[rest+1][N+1];//记录表
for (int i = 0 ; i <=rest ; i++)
{
for (int j = 0 ; j <=N ; j++)
{
dp[i][j] = -1;