1、计算机算法(2),汪洋 ,主要内容,背包问题 搜索树 递归,0-1背包问题,给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?0-1背包问题是一个特殊的整数规划问题。,0-1背包问题,设所给0-1背包问题的子问题,的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。,例子,背包容量为9,要装入4个体积为2,3,4,5的物品,价值分别为3,4,5,7。,void knapsack() int
2、 i, j;for (i = 0; i = c; +i)m0i = 0;for (i = 0; i = n; +i)mi0 = 0;for (i = 1; i = n; +i)for (j = 1; j = c; +j) if (j wi)mij = mi - 1j;elsemij = max(mi - 1j, mi - 1j - wi + wi); ,化简,思考:需要这么多行么?,int mVal,nVal; int *dp; int max(int a, int b) return (a b ? a : b); void ZeroOnePack(int cost, int weight)
3、for (int i = nVal; i = 0; i-)dpi = max(dpi, dpi-cost + weight); int main(int argc, char* argv) mVal = 4;nVal = 9;int c4 = 2,3,4,5;int w4 = 3,4,5,9;dp = new intnVal+1;memset(dp,0,(nVal+1)*sizeof(int);for(int i = 0;imVal;i+)ZeroOnePack(ci,wi);coutdpnValendl;delete dp;return 0; ,再化简,再思考:需要每次从nVal查到0么?,
4、void ZeroOnePack(int cost, int weight) for (int i = nVal; i = cost; i-)dpi = max(dpi, dpi-cost + weight); ,搜索树,深度优先搜索 广度优先搜索,初识“图”,初识“图”,邻接矩阵:,邻接表,广度优先搜索,宽度优先检索 从结点v开始,给v标上已到达(或访问)标记此时称结点v还没有被检测,而当算法访问了邻接于某结点的所有结点时,称该结点被检测了。 访问邻接于v且尚未被访问的所有结点这些结点是新的未被检测的结点。将这些结点依次放置到一未检测结点表(队列Q)中(末端插入) 。 标记v已被检测。 若未
5、检测结点表为空,则算法终止;否则 从未检测结点表的表头取一结点作为下一个待检测结点,重复上述过程。,算法5.6 宽度优先检索算法procedure BFS(v)/宽度优先检索G,它从结点v开始。所有已访问结点被标记为VISITED(i)=1。/VISITED(v)1;uv /VISITED(n)是一个标示数组,初始值 VISITED(i)=0, 1in /将Q初始化为空 /Q是未检测结点的队列/loopfor 邻接于u的所有结点w doif VISITED(w)=0 then /w未被检测/call ADDQ(w,Q) /ADDQ将w加入到队列Q的末端/VISITED(w)1 /同时标示w已被
6、访问/endifrepeatif Q 为空 then return endifcall DELETEQ(u,Q) /DELETEQ取出队列Q的表头,并赋给变量u/repeatend BFS,深度优先搜索,从结点v开始,首先给v标上已到达(或访问)标记,同时中止对v的检测,并开始对邻接于v且尚未被访问的结点u检测。在这样的u均被检测后,再恢复对v的检测。当所有可到达的结点全部被检测完毕后,算法终止。,procedure DFS(v)/已知一个n结点的无向(或有向)图G(V,E)以及初值已置为零的数组VISITED(1:n)。这个算法访问由v可以到达的所有结点。/VISITED(v)1for 邻接于v的每个结点w doif VISITED(w)0 then call DFS(w) endifrepeatend DFS,递归函数,函数的运行机制 例子,