008-算法-分支界限法

一、概念:与贪婪法一样,这种方法也是用来为组合优化问题设计求解算法的,所不同的是它在问题的整个可能解空间搜索,所设计出来的算法虽然时间复杂度比贪婪算法高,但它的优点是与穷举法类似,都能保证求出问题的最佳解,而且这种方法不是盲目的穷举搜索,而是在搜索中通过界限,可以中途停止对某些不可能得到的最优解的子空间。进一步搜索(类似人工智能中的剪枝),故它比穷举法效率更高。

二、基本思路:

分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。 此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

常见的两种分支限界法
(1)队列式(FIFO)分支限界法
    按照队列先进先出(FIFO)原则选取下一个结点为扩展结点。
(2)优先队列式分支限界法
    按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。
demo:


支界限算法 - 具体问题(背包问题)

在历届NOIP竞赛中,有4道初赛题和5道复赛题均涉及到背包问题,所谓的背包问题,可以描述如下:

一个小偷打劫一个保险箱,发现柜子里有N类不同大小与价值的物品,但小偷只有一个容积为M的背包来装东西,背包问题就是要找出一个小偷选择所偷物品的组合,以使偷走的物品总价值最大。 
如有4件物品,容积分别为: 3 4 5 8 
对应的价值分别为: 4 5 7 10 
小偷背包的载重量为:12 
则取编号为1 2 3的物品,得到最大价值为16。

* 0/1背包问题的分支定界法算法*/ #include<stdio.h> #include<stdlib.h> #define MAXNUM 100 struct node { int step ; double price ; double weight ; double max,min ; unsigned long po ; } ; typedef struct node DataType ; struct SeqQueue { /* 顺序队列类型定义 */ int f,r ; DataType q[MAXNUM]; } ; typedef struct SeqQueue*PSeqQueue ; PSeqQueue createEmptyQueue_seq(void) { PSeqQueue paqu ; paqu=(PSeqQueue)malloc(sizeof(struct SeqQueue)); if(paqu==NULL) printf("Out of space!! \n"); else paqu->f=paqu->r=0 ; return paqu ; } int isEmptyQueue_seq(PSeqQueue paqu) { return paqu->f==paqu->r ; } /* 在队列中插入一元素x */ void enQueue_seq(PSeqQueue paqu,DataType x) { if((paqu->r+1)%MAXNUM==paqu->f) printf("Full queue.\n"); else { paqu->q[paqu->r]=x ; paqu->r=(paqu->r+1)%MAXNUM ; } } /* 删除队列头元素 */ void deQueue_seq(PSeqQueue paqu) { if(paqu->f==paqu->r) printf("Empty Queue.\n"); else paqu->f=(paqu->f+1)%MAXNUM ; } /* 对非空队列,求队列头部元素 */ DataType frontQueue_seq(PSeqQueue paqu) { return(paqu->q[paqu->f]); } /* 物品按性价比从新排序*/ void sort(int n,double p[],double w[]) { int i,j ; for(i=0;i<n-1;i++) for(j=i;j<n-1;j++) { double a=p[j]/w[j]; double b=p[j+1]/w[j+1]; if(a><b) { double temp=p[j]; p[j]=p[j+1]; p[j+1]=temp ; temp=w[j]; w[j]=w[j+1]; w[j+1]=temp ; } } } /* 求最大可能值*/ double up(int k,double m,int n,double p[],double w[]) { int i=k ; double s=0 ; while(i><n&&w[i]><m) { m-=w[i]; s+=p[i]; i++; } if(i><n&&m>0) { s+=p[i]*m/w[i]; i++; } return s ; } /* 求最小可能值*/ double down(int k,double m,int n,double p[],double w[]) { int i=k ; double s=0 ; while(i<n&&w[i]><=m) { m-=w[i]; s+=p[i]; i++; } return s ; } /* 用队列实现分支定界算法*/ double solve(double m,int n,double p[],double w[],unsigned long*po) { double min ; PSeqQueue q=createEmptyQueue_seq(); DataType x= { 0,0,0,0,0,0 } ; sort(n,p,w); x.max=up(0,m,n,p,w); x.min=min=down(0,m,n,p,w); if(min==0)return-1 ; enQueue_seq(q,x); while(!isEmptyQueue_seq(q)) { int step ; DataType y ; x=frontQueue_seq(q); deQueue_seq(q); if(x.max<min)continue ; step=x.step+1 ; if(step==n+1)continue ; y.max=x.price+up(step,m-x.weight,n,p,w); if(y.max>=min) { y.min=x.price+down(step,m-x.weight,n,p,w); y.price=x.price ; y.weight=x.weight ; y.step=step ; y.po=x.po<<1 ; if(y.min>=min) { min=y.min ; if(step==n)*po=y.po ; } enQueue_seq(q,y); } if(x.weight+w[step-1]<=m) { y.max=x.price+p[step-1]+ up(step,m-x.weight-w[step-1],n,p,w); if(y.max>=min) { y.min=x.price+p[step-1]+ down(step,m-x.weight-w[step-1],n,p,w); y.price=x.price+p[step-1]; y.weight=x.weight+w[step-1]; y.step=step ; y.po=(x.po<<1)+1 ; if(y.min>=min) { min=y.min ; if(step==n)*po=y.po ; } enQueue_seq(q,y); } } } return min ; } #define n 4 double m=15 ; double p[n]= { 10,10,12,18 } ; double w[n]= { 2,4,6,9 } ; int main() { int i ; double d ; unsigned long po ; d=solve(m,n,p,w,&po); if(d==-1) printf("No solution!\n"); else { for(i=0;i<n;i++) printf("x%d is %d\n",i+1,((po&(1><<(n-i-1)))!=0)); printf("The max weight is %f\n",d); } getchar(); return 0 ; }

008-算法-分支界限法

时间: 2024-11-02 10:11:57

008-算法-分支界限法的相关文章

五类常见算法小记 (递归与分治,动态规划,贪心,回溯,分支界限法)

近日复习了一些算法知识,小记于此 递归与分治法 直接或间接地调用自身的算法称为递归算法. 递归是算法设计与分析中常用的一种技术,描述简单且易于理解. 分治法的设计思想是将一个规模为n难以解决的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同. 递归地解这些子问题,然后将各子问题的解合并得到原问题的解. 典型例子:Fibonacci数列,阶乘,Hanoi塔:二分法搜索.快速排序.合并排序. 动态规划法 动态规划过程是:根据当前(阶段)状态,采取相应的决策,引起状态的转移.如下图,一

分支界限法(BFS)

分支界限法类似回溯法,也是在问题的解空间上搜索问题解的算法,其求解目标是找出满足约束条件的一个解(回溯是找出所有的解)或是在满足条件的解中找出最优解. 搜索策略:在扩展结点处,先生成其所有的儿子节点(分支),然后再从当前的活结点表中(根据每一活结点计算出的函数值)选择最有利的结点作为下一个扩展结点. 从活结点表中选择下一扩展结点的不同方式导致不同的分支界限法: 1.队列式(FIFO)分支界限法 2.优先队列式分支界限法 基本思想:以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树.

最小重量问题的分支界限法的C++实现方案

*1.问题描述:* *2.解题思路* 这个题目基本思想是 利用分支界限法, 核心就是需要设计一个 优先级标准, 这里我们将 问题的层数,也就是第i个部件作为优先级, 对于相同i的部件,以重量更小的作为优先级的评价标准,然后借助标准库中的优先级队列实现,分支界限法 查找目标. 另外需要注意的是, 使用标准库中的优先级队列时候需要自己重载operator< ,而且一定要有const,233333333 3.源代码 3.1MinMachine.h #pragma once #include <que

分支界限法

适用: 要求在某约束条件下,求得由n个元素组成的全部解或最优解(解是个集合) 注意是:它同回溯法解决问题类似,关键的不是在于,这个算法解决的问题,解集合中的元素先后顺序是有影响的: 步骤: 1.把解集合的所有可选元素,整理为树状或图状结构 2.由于解集合元素的先后顺序有关.所以,如果,第m个元素选择后,顺序已然不正确,那么就没有必要继续向深层遍历.基于这一点, 这里应该选择宽度优先遍历 3.如果顺利遍历到最后一个元素,那么表示这是一个解 特别说明: 本算法与回溯法思想相近,由于一个与元素顺序无关

分治法、动态规划、回溯法、分支界限法、贪心算法

转:http://blog.csdn.net/lcj_cjfykx/article/details/41691787 分治算法一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)…… 任何一个可以用计算机求解的问题所需的计算时

第六章-分支界限法

扩展结点:当前结点. 活节点:扩展结点的所有儿子中,经过限界剪枝后剩下的儿子. 分支限界法: 分支:当前扩展结点一次性,产生所有儿子. 限界:在结点扩展的过程中,通过计算结点的上界或下界来大量剪掉树的不合格分支,从而提高搜索效率. 广度优先策略: 一开始,只有根结点是唯一的活结点. 一个活节点一旦成为扩展结点,将一次性产生所有儿子,然后通过"限界"舍弃掉导致不可行解或非最优解的儿子,其余儿子加入活节点表中(队列):然后从活结点表中,弹出队首结点(先进先出)作为当前扩展结点--重复该过程

分支界限法 | 装载问题(先入先出队列式分支限界法)

输入要求 有多组数据.每组数据包含2行.第一行包含2个整数 C(1 <= C <= 1000).和 n(1 <= n <= 10),分别表示的轮船的载重量和集装箱的个数.第二行包含n个整数,依次表示n个集装箱的重量w.(0 <= w <= 1000) 输出要求 对于每组输入数据,按出队次序输出每个结点的信息,包括所在层数,编号,已装载重链,轮船上集装箱的个数每个结点的信息占一行,如果是叶子结点且其所代表的装上轮船的集装箱的个数大于当前最优值(初始为0),则输出当前最优值

五大算法基本思想—分治,动态规划,贪心,回溯,分支界限

一.算法理解 算法是什么,即是按照一定的步骤,一步步去解决某个问题,解决问题的方法步骤就称为算法,例如数学中我们学过的做一个运算,解一个方程,等等,都需要有一个清晰的思路,一步步地去完成.可以说算法就在身边. 算法和计算机有什么关系,计算机它是机器,没有人类的大脑可以思考,但是它怎么完成我们交给他的人物的呢,就是通过算法(当然是人为预先设计好的),计算机解决任何问题都要依赖于算法,没有算法也就没有计算机. 为了计算机能更好更有效率的运行,算法就必须足够好,既要正确易理解,又要可靠效率.下面来研究

分支界定法详解

分支界定法是求解整数线性规划最优解的经典方法. 定义: 对有约束条件的最优化问题(其可行解为有限数)的所有可行解空间恰当地进行系统搜索,这就是分支与界定的内容.通常把全部解空间反复地分割为越来越小的子集,称为分枝:并对每个子集内的解集计算一个目标下界(对于最小值问题),这称为定界.在每次分枝后,若某个已知可行解集的目标值不能达到当前的界限,则将这个子集舍去.这样,许多子集不予考虑,这称为剪枝.这就是分枝界限法的思路. 背景: 分枝界限法可以用于求解纯整数或混合的整数规划问题.在上世纪六十年代由L