回溯,递归以及二叉树,多叉数

许多问题可以转化为二叉树的遍历
包括八皇后问题,幂集问题,全排列问题,组合问题,背包问题
不信?
试试看
其实只要涉及对元素进行是否判断的问题,都可以用树来解决.(显然废话,但是很久以来没有注意到)

1 八皇后问题
就是对64个单元格进行是否判断
当"是"怕判断达到8个就再判断是否满足八皇后的条件
然后回溯
而遍历树的过程就是用递归法.
(代码只是实例,不保证可以运行)
void  main()
{
     
int a [64= {1,2 ,3 ....64};
     
int flag[64= {0};
     BHH(
0,64,a);
}


void  BHH( int  i, int  n, int [] a)
{
      
if (flag 中的元素不满足条件,包括不能在同行的类似问题,插入元素超过8个)
          
{return;}

      
if (i ==n 而且满足条件)
          
{     //打印      }

      flag[i] 
= 1
                BHH(i
+1,n,a);
      flag[i]
= 0;
                 BHH(i
+1,n,a);
      
}



2 幂集问题
集合{1,2,3,4,5}的全部幂集

判断每个元素分别进行取舍得到一个二叉树.遍历之即可.

PowerSet( i , n  ,a )   //  i 表示第i 个元素,n表示元素的总共个数
{
    
if (i == n)
       
{
         
//打印结果,在这里只打印标记为1的
          for (int t 
= 0 ; t < n ; t++)
             
if ( flag[t] == 1)
                 printf(
"%d " ,a[t]);
          printf(
" ");
        }


    
//二叉树的左孩子,即"是"的情况
    flag[i] = 1 ;
    PowerSet (i
+1,n,a);
    
     
//二叉树的右孩子,即"否"的情况
     flag[i]= 0;
     PowerSet(i
+1,n,a)
}


// 调用
void  main()
{
      
int a[5=  {1,2,3,4,5};
          int flag[5] = {0};  //记录a中每个元素的选择情况
      PowerSet(
0,5,a);
}
 

3 全排列
当然这里就不是二叉树,而是多叉数了
因为要判断的是第一个位置是1 或者 2或者...
比如 对 1 2 3 4 5  进行全排
根节点下面是 1 2 3 4 5 共5个结点
然后1下面的是 2 3 4 5
void  main()
{
   
int a[5= {1,2,3,4,5};
       int flag[5] = 0;         //记录第i个位置填入的数字在a中的下标.
   Pailie(
0,5,a);
}


void  Pailie( int  i , int  n, int  [] a)
{
    if (i == n )
        {
           //打印,按照flag记录的下标的顺序打印a
        }

        for (a.length)   //a的长度要变化,以提高效率.
           {
               flag[i] = a[j]
               把a[j]除去,得到新的a
               Pailie (i+1,n,a);
           }
          
}


3 n个数选m的组合问题
就是幂集问题嘛
只不过要判断幂集的元素个数是否为m个.

4 把n个相同的球放到m个不同的盒子中,方法有多少种?
第一个盒子可以有 a1 =  0~n个
第二个盒子...          0~ n-a1个
然后用上面的排列案例中的多叉数就可以了

5 背包问题
其实就是幂集问题啦
只不过第i层的各个节点是第i个物品的个数
所以也是一个多叉数.

可以看到
只要清楚自己的步骤和第i层的关系
一切都很明了

当然,具体问题还要具体分析,这种方法对于可以分解为yes,no或者有限个情况的问题是好解决的

但是,比如对于汉诺塔问题
就只能老实的使用递归了.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值