递归

栈的应用:递归
将函数的调用位置,局部变量和寄存器等信息作为1种称作激活记录的数据结构。(图P147和P148)
用通用方法将大型问题简化为类似性质但规模更小的问题。
一直递归直到将子问题简化到无需递归即可解答。

  • 关键步骤:确定普遍使用的划分原则
  • 停止规则:确定算法能够处理特例,例如什么不做时能正常返回。
  • 递归函数执行关键步骤直到符合停止规则

将指令放在一个区域,将其他数据放在每个用户独立的区域

注意尾部递归:当函数最后执行的语句(不一定是程序的最后一句)是递归调用。可以通过while/do while循环改为迭代减少空间复杂度。

通过递归树来判断使用迭代还是递归:

  1. 当递归树不存在重复任务(例如斐波那契数列P150)且树很茂密,考虑使用迭代;
  2. 树的形式简单考虑迭代。
  3. 迭代(自底向上,由已知到未知)和栈能代替递归,递归(自顶向下,从未知分解为已知)能替代栈。

范例:

  1. 分而治之
  2. 树结构
  3. 回溯:

    • 构造部分解,当与问题需求不一致时,移去最近构造的解并倒退,尝试另一种可能。
    • 适合随着不断的测试能减少可能的数量

八皇后问题(皇后可以横/竖/对角线)
solve_form函数:从给定的皇后位置递归查找解答
Queens configuration:已选择的路径
configuration:棋盘上所有的位置

solve_form(Queens configuration)
检查Queens configuration是否违背规则,违背直接返回
if已有八个 打印结束
else
  for_each configuration未选择的位置{
     选择下一个皇后在configuration的位置
     solve_form(Queens configuration);
     移除
  }
int main()
{
   int board_size;//放置的皇后数量
   cin>>board_size;
   if(board_size<0 || board_size>max_board )
     cout<<"…"<<endl;
   else{
     Queens_configuration(board_size);
     solve_form(configuration);
   }
}
//根据第count行第col列的格子是否能够放置
bool Queens::unguarded(int col)const;
//没违反则插入,count+1
bool Queens::insert(int col);
//已摆放的数量是否等于board_size
bool Queens::is_sovled()const;
solve_form(Queens_configuration)
{
   if( configuration.is_solved() )
      configuration.print();
   else
      for(int col=0;col<configuration.board_size;
      ++col)
         if( configuration.unguarded(col) ){
           configuration.insert(col);
           solve_form(configuration);
           configuration.remove(col);
         }           
}
const int max_board=0;
class Queens{
public:
   Queens(int size);
   bool is_solved()const;
   void print()const;
   //判断是否可以放置
   bool unguarded(int col)const;
   void insert(int col);
   void remove(int col);
   int board_size;
private:
   int count;
   bool queen_square[max_board][max_board];
};
Queens::Queens(int size)
{
   board_size=size;
   count=0;
   for(int row=0;row<board_size;++row)
      for(int col=0;col<board_size;++col)
         queen_square[row][col]=false;
}
void Queens::insert(int col)
{
   queen_square[count-1][col]=true;
}
bool Queens::unguarded(int col)const
{
   int i;
   bool ok=true;
   for(i=0; ok&&i<count ;++i)
      ok= !queen_square[i][col];
   for(i=0; ok&&count-i>=0&&col+i<board_size ;++i)
      ok= !queen_square[i][col];
   return ok;
}

优化

  • 建议1:将所有不能放置的数组同时标记
  • 建议2:使用3个数组记录可以使用的格子
class Queens{private:
   int count;
   bool col_free[max_board];
   bool upward_free[max_board];
   bool downward_free[max_board];
   int queen_in_row[max_board];
};
bool Queens::unguarded(int col)const
{
   return col_free[col]
          && upward_free[count+col];
          && downward_free[count+col+board_size-1];
}

游戏树:
2个玩家轮流选择123中的一个数字,并且不能选择上一轮的数字。2个玩家所选的数字之和等于8时的玩家获胜;使和大于8的玩家失败。
由于在合理的运行时间内无法探查所有的分支,只能通过评价函数返回利益的估计值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值