摘要:
[问题]M个交易员在圆桌旁围坐一圈,将N(N < M)个交易品种分配给他们研究。每人分配一个,要求相邻的两个人所分配到的交易品种不相同。编程计算共有多少种分配方式[解析]将圆桌抽象成一个圆,将交易员抽象成圆上的一个个小球(类似于项链),将分配M个交易品种抽象成分配M种颜色。从任意一个球开始,将其编号为1。对于1号球,有M种颜色分配方案。设n个球中的第1个球的颜色设定后,还有F(n)种颜色分配方案,则颜色分配方案的总数为M * F(N). 下面来求F(N)。从1号球开始选定3个球,分别编号为1、2、3.下面分两种情况讨论: (1)如果3号球与1号球颜色相同,则1、2、3这3个球共有M... 阅读全文
摘要:
[问题]某推销员要到若干城市去推销商品,各城市之间的路程如下图所示。他要选定一条从驻地1出发,经过每个城市一次,最后回到驻地的路线,并使总路程最短。 [解析]将该问题的解空间组织如下: 这棵解空间树中从根节点B到任一叶节点的路径均定义了图的一条周游路线,而图的每一条周游路线都恰好对应于解空间树中从根节点B到某一叶节点的路径。 最后从根节点B开始,对解空间树进行DFS。所选用的剪枝函数为判断当前已花费的路程是否小于当前已找到的最短周游路径的长度,属于限界函数。搜索过程中每到达一个叶节点,则记录当前周游路径的总路程,并与已找到的最小值进行比较,根据比较结果来更新最小值。 代码如下:/... 阅读全文
摘要:
[问题]给定n种物品和1个背包,背包允许的最大重量为Capacity。物品i的重量为weight[i],价值为value[i]。与0-1背包问题(每种物品只有装入背包或不装入背包两种选择)不同的是,在选择物品i装入背包时,可以只装入物品i的一部分。 问应当怎样选择物品装入背包,使背包中的物品的总价值最大? [解析]该问题可用贪心法解决,所采取的贪心策略如下: (1)计算每种物品的单位重量的价值value[i]/weight[i] (2)依照贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。 (3)若将这种物品全部装入背包后,背包仍有剩余容量,则选择单位重量价值次高的物品... 阅读全文
摘要:
[问题]设有n个活动的集合E={1,2,……,n}(按其结束时间排序),其中每个活动都要使用同一个场所,而在同一时间内只有1个活动能使用该场所。每个活动i的开始时间和结束时间分别为begin[i]和finish[i]。求E的最大相容子集合。 [解析]先选择活动1,活动1具有最早的完成时间。下面证明该问题具有贪心选择性质,即该问题有一个最优解以贪心选择开始,即该最优解中包含活动1。证明过程如下: 设子集A是该问题的一个最优解,且A中的活动按结束时间排序,其第一个活动为k: (1)若k=1,则A就是以贪心选择开始的最优解。 (2)若k>1,则设子集B=A-{k}U{1}。由于finis... 阅读全文
摘要:
[问题]设X[1...n]和Y[1...n]为两个数组,每个都包含n个已排序好的数。给出一个求数组X和Y中所有2n个元素的中位数的、O(lgn)时间的算法。 [解析]O(lgn)的时间复杂度就是二分查找的复杂度。首先给出一个观察:如果所有元素的中位数是X,那么从数组中同时删除num个小于X的的元素和num个大于X的元素后,产生的新集合的中位数还是X。考虑如下思路求解:每次比较A,B数组的中项元素A[n/2],B[n/2],代码实现如下:int FindMiddleElement(int A[],int B[],int n) { if (n == 1) { ... 阅读全文
摘要:
[问题]给定n种物品和1个背包,背包允许的最大重量为Capacity。物品i的重量为weight[i],价值为value[i]。问应当选择哪些物品装入背包,使背包中的物品的总价值最大?[解析]因为每种物品只有装入背包或不装入背包两种选择,所以该问题称为0-1背包问题。方法1.动态规划法按照从1到n的顺序来依次决定每种物品是否装入背包中。设轮到决定物品i时背包的剩余容量为C,此时利用从i开始的所有剩余物品和背包的剩余容量可以得到的最大价值为f(i,C),则(1)若选择将物品i装入背包,则所得的最大价值为f(i+1,C-weight[i])+value[i](2)若选择将物品i不装入背包,则... 阅读全文
摘要:
[问题]一个给定序列的子序列是指在该序列中删除若干元素后所得的序列,但删除过程中不能打乱元素的顺序。例如序列{B,C,A,B}是序列X={A,B,C,B,D,A,B}与序列Y={B,D,C,A,B,A}的一个最长公共子序列。给定序列X={x1,x2,……,xm}与序列Y={y1,y2,……,yn},求其最长公共子序列的长度 [解析]设序列X={x1,x2,……,xm}与序列Y={y1,y2,……,yn}的最长公共子序列为序列Z={z1,z2,……,zk},则有如下结论(均可由反证法证明) (1)若xm=yn,则zk=xm=yn,且序列Zk-1是序列Xm-1和序列Yn-1的最长公共子... 阅读全文
摘要:
[问题]给定一个包含n个矩阵的链乘式,通过对矩阵加括号来变换矩阵相乘的次序。问应当怎样加括号才能使求解过程中乘法运算的总次数最少?最少的总次数是多少? [解析]假设矩阵链乘式A1A2A3A4A5的最优解为((A1)(A2A3))(A4A5) ,则(A1)(A2A3)必为链乘式A1A2A3的最优解(由反证法易得)。由此可知,该问题具有最优子结构性质。递推式如下; 设链乘式AiAi+1Ai+2……Aj中矩阵An的列数为Columns[n],其划分的形式为(Ai……Ak)(Ak+1……Aj),则相应的乘法运算的总次数为,对左括号进行计算求得矩阵ALeft的过程中的最少总次数f(i)(k),加... 阅读全文
摘要:
1.分治 分治法的设计思想是,将一个难以直接解决的大问题,分割成k个规模较小的子问题,这些子问题相互独立,且与原问题相同,然后各个击破,分而治之。 分治法常常与递归结合使用:通过反复应用分治,可以使子问题与原问题类型一致而规模不断缩小,最终使子问题缩小到很容易求出其解,由此自然导致递归算法。 根据分治法的分割原则,应把原问题分割成多少个子问题才比较适宜?每个子问题是否规模相同或怎样才为适当?这些问题很难给与肯定的回答。但人们从大量实践中发现,在使用分治法时,最好均匀划分,且在很多问题中可以取k=2。这种使子问题规模大致相等的做法源自一种平衡子问题的思想,它几乎总是比使子问题规模不等... 阅读全文
摘要:
A*算法的目的是找到一条从起始状态到最终状态的最短路径。在A*算法中,需要在每个点计算启发函数:f(S)=g(S)+h(S),其中g(S)是从起点到S点的距离,h(S)是对从S点到终点的最短距离的估计值。 如果把g(S)当作深度,又令h(S)=0,则A*算法就变成了BFS。A*算法对BFS的改进在于把BFS所用到的队列改成按启发函数值排列的优先队列。假设从状态S抵达终点的最短距离为H(S),那么启发函数中的h(S)必须满足h(S)<=H(S)。在此基础上,h和实际的距离越接近,需要计算的节点就越少,效果就越好。如果h(S)=0,此时A*算法就变成了BFS,效果最差。在解8数字谜题时,如果 阅读全文