递归的经典问题

一、斐波那契数列

有一个数列 1,1,2,3,5,8,13 ...,给你一个整数 n,用递归的方式求出它的值。

思路分析:

(1)当 n 等于 1 或 n 等于 2 时,斐波那契数是 1

(2)当 n > 2 时,斐波那契数是前两个数的和

根据规律可写出如下代码:

int fibonacci(int n)
{
    if(n == 1 || n == 2)
        return 1;
    else
    {
        return fibonacci(n - 1)+fibonacci(n - 2);
    }
}

 

二、猴子吃桃

有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个,以后每天猴子都吃其中的一半,然后再多吃一个,当到第十天时,猴子想再吃(即还没吃),却发现只有一个桃子了。求最初一共有多少个桃子。

 思路分析(逆推):

(1)day = 10 时,有 1 个桃子

(2)day = 9 时,有 ( day 10 + 1 )* 2 = 4 个桃子

(3)day = 8 时,有( day 9 + 1 )* 2 = 10 个桃子

得出规律是 前一天的桃子 =( 后一天的桃子 + 1 )* 2,代码如下

int peach(int day)
{
    if(day == 10)
        return 1;
    else if(day >= 1 && day < 10)
    {
        return (peach( day + 1 ) + 1) * 2;
    }
    else
    {
        return -1;            //不在范围内的天数返回-1
    }
}

 

三、迷宫问题

迷宫问题求解得到的路径与设置的找路策略(这里规定找路顺序为 下—>右—>上—>左)有关

因为我们是递归的找路,我们这里给出几点规定:

1 . 规定 map 数组各个值的含义:0 表示可以走,1 表示障碍物,2 表示探测过可以走,3 表示探测过但是走不通(即死路)

2 . 确定递归出口,当 map [ 6 ] [ 6] = 2 时,说明找到通路,否则继续找

思路分析:

(1)先创建迷宫,用二维数组表示,初始化二维数组

int [][] map = new int[8][8];
for(int i = 0 ; i < map.length ; i++)
{
    map[0][i] = 1;
    map[7][i] = 1;
    map[i][0] = 1;
    map[i][7] = 1;
}
map[2][3] = 1;
map[3][5] = 1;
map[4][2] = 1;
map[6][5] = 1;

创建好的迷宫如图所示:

(2)定义 findWay 方法去找出迷宫的路径,如果找到,返回 true,否则返回 false

boolean findWay(int [][] map,int i,int j)//i,j 表示当前位置
{
    if(map[6][6] == 2)     //递归出口
        return true;
    else
    {
        if(map[i][j] == 0) //当前位置没走过,可以走
        {
            map[i][j] = 2; //先假定这个位置可以走通

            //使用找路策略来确定该位置是否真的可以走通
            if( findWay (map, i+1, j ))      //先走下
                return true;
            else if( findWay (map, i, j+1 )) //右
                return true;
            else if( findWay (map, i-1, j )) //上
                return true;
            else if( findWay (map, i, j-1 )) //左
                return true;
            else
            {
                map[i][j] = 3;
                return false;
            }
            
        }else{            //map[i][j] = 1, 2, 3
             return flase; 
        }
    }
}

 

四、汉诺塔问题

将全部盘子从 A 塔搬运到 C 塔,可以借助 B 塔,并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘 

思路分析:

(1)当只有一个盘子时,将 A 塔上的盘子直接移动到 C 塔

(2)当有多个盘子时,除了 A 塔最下面的一个盘子,其余的盘子都移到 B 塔上,然后就可以直接将 A 塔上的一个盘子直接移动到 C 塔了

(3)然后再借助 A 塔,将 B 塔上的所有盘子移动到 C 盘

代码如下:

public void move(int num,char a,char b,char c)   //num表示要移动盘子的个数
{
    if(num == 1)
        System.out.println(a + "——>" + c);
    else
    {
        move(num-1, a, c, b);    //先移动上面所有盘到b,借助c
        System.out.println(a + "——>" + c);//把最下面的这个盘,移到c
        move(num-1, b, a, c);    //把b塔上的所有盘,借助a,移动到c
    }
}

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里给出一个简单的 Gurobi 递归优化问题的示例代码,可以供您参考: ```python import gurobipy as gp from gurobipy import GRB # 定义子问题求解函数 def solve_subproblem(model, x, y): # 定义变量和约束 z = model.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS, name="z") model.addConstr(x + y >= 1 + z) model.setObjective(z, GRB.MINIMIZE) # 求解子问题 model.optimize() # 获取子问题的最优解和最优值 z_val = z.X obj_val = model.ObjVal return z_val, obj_val # 定义主问题的变量和约束 model = gp.Model("Recursive Optimization") x = model.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS, name="x") y = model.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS, name="y") model.addConstr(x + y >= 1) # 定义递归过程 def recursive_solve(model, x, y): # 求解子问题 z_val, obj_val = solve_subproblem(model, x, y) # 当子问题最优值小于0.5时,递归求解 if obj_val < 0.5: model.addConstr(x + y <= 1 + z_val) recursive_solve(model, x, y) # 求解主问题 model.setObjective(x + y, GRB.MAXIMIZE) model.optimize() # 进行递归求解 recursive_solve(model, x, y) # 输出最优解和最优值 print("x:", x.X) print("y:", y.X) print("obj:", model.ObjVal) ``` 在这个示例代码中,我们定义了一个主问题和一个子问题,然后通过递归求解来优化主问题的解。在递归过程中,我们首先求解子问题,并将其最优解和最优值返回到主问题中。然后,如果子问题的最优值小于0.5,我们就添加一个新的约束到主问题中,这个约束将限制主问题的解空间,使得我们可以更好地利用子问题的信息进行优化。最后,我们通过调用 `recursive_solve()` 函数来进行递归求解,直到找到最优解为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值