博文
工作分配问题(2005-12-01 11:30:00)
摘要:【试验题目】
工作分配问题。设有n件工作要分配给n个不同的人去完成。将工作i分配给第j个人所需要花费的费用为Cij。设计一个算法,为每个人都分配一件不同的工作,并使总费用达到最小。
【程序代码】
#include<iostream>
#include<ctime>
#include<iomanip>
using namespace std;
void Swap(int &x,int &y);
class WorkAssignment
{
friend void WorkAsmt(int **c,int n,int *bestx);
private:
void Backtrack(int i);
int **c,//个作业所需要的处理时间
*x,//当前作业调度
*bestx,//当前最优分配
best,//当前最优值
n,//作业数
cx;//当前值
};
//回溯
void WorkAssignment::Backtrack(int i)
{
if(i......
0—1背包问题的回溯法(2005-11-27 01:23:00)
摘要:【实验目的】
学习掌握回溯算法。
【实验内容】
用回溯法求解0—1背包问题,并输出问题的最优解。0—1背包问题描述如下:
给定n种物品和一背包。物品i的重量是Wi,其价值为Vi,背包的容量是c,问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。
【实验条件】
Microsoft Visual C++ 6.0
【需求分析】
对于给定n种物品和一背包。在容量最大值固定的情况下,要求装入的物品价值最大化。
【设计原理】
一、回溯法:
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。
二、算法框架:
1、问题的解空间:应用回溯法解问题时,首先应明确定义问题的解空间。问题的解空间应到少包含问题的一个(最优)解。
2、回溯法的基本思想:确定了解空间的组织结构后,回溯法就从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。换句话说,这个结点不再是一个活结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。
运用回溯法解题通常包含以下三个步骤:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先的方式搜索解空间,并且在搜索过程中用......
设计一个线性时间算法,确定T[0:n]是否有一个主元素。(2005-11-12 23:26:00)
摘要:【实验目的】
掌握熟悉地跪于分治策略算法设计。
【实验内容】
设T[0:n-1]是n个元素的一个数组。对任一元素x,设S(x)={i|T[i]=x}。当|S(x)|>n/2时,称x为T的主元素。设计一个线性时间算法,确定T[0:n]是否有一个主元素。
【实验条件】
Microsoft Visual C++ 6.0
【需求分析】
算法需要求出在数组T[0:n]中出现次数最多的元素x出现的次数k.,如果k>(n+1)/2,则此数组有主元素,否则没有。
【设计原理】
算法需要求出在数组T[0:n]中出现次数最多的元素x出现的次数k.,如果k>(n+1)/2,则此数组有主元素,否则没有。先用Select算法求出数组中第(n+1)/2大的数,然后扫描数组,记录第(n+1)/2大的数在数组中出现的次数,如果k>(n+1)/2,则此数组有主元素,否则没有。
【概要设计】
数据:
a[N]:用于存放数组T[0:n-1];
int sign:如果存在主元素,sign=true;否则:sign=false;
函数:
int Partition(int a[],int p,int t,int x);
//数组划分,将小于等于x的元素移到x左边,大于x的元素移到x右边。
void Swap(int &x,int &y);
//交换元素x和y。
void QuickSort(int a[],int p,int r);
//快速排序。
int Select(int a[],int p,int r,int k);
//线性时间选择,找到第k大的数。
int MainNum(int a[],int p,int r);
//判断是否具有主元素。
【详细设计】
#include<iostream>
#include <ctime>
using namespace std;
//函数声明
int Partition(int a[],int p,int t,int x);
void Swap(int &x,int &y);
void QuickSort(......
在O(n*n)时间内出由n个数组成的序列的最长单调递增子序列。(2005-11-05 00:14:00)
摘要:【实验目的】
练习掌握动态规划算法。
【实验内容】
设计一个O(n*n)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
【实验条件】
Microsoft Visual C++ 6.0
【需求分析】
题目要求在O(n*n)的时间内找出n个数组成的序列的最长单调递增子序列,需要用到排序算法,查找最长公共子序列的算法。
【设计原理】
将数组a复制到数组x,先用排序算法将数组x排序,在调用查找最长公共子序列的算法求出数组a和数组x中的最长公共子序列,因为数组x是单调递增的,所以由此求出来的最长公共子序列就是题设所求的最长单调递增子序列。
【概要设计】
数据:
N:数组元素个数。
a[N]:用于存放数组。
X[N]:复制数组a[N],并排序。
c[i][j]:存储a和x的最长公共子序列的长度。
b[i][j]:记录c[i][j]的值是由哪一个资问题的解得到的。
函数:
int Partition(int a[],int p,int t,int x);
//数组划分,将小于等于x的元素移到x左边,大于x的元素移到x右边。
void Swap(int &x,int &y);
//交换元素x和y。
void QuickSort(int a[],int p,int r);
//快速排序。
void LCSL(int m,int n,int *x,int *y,int **c,int **b);
//计算最长公共子序列长度。
void LCS(int i,int j,int *x,int **b);
根据b[i][j]的内容打印a,x数组的最长公共子序列。
【详细设计】
#include<iostream>
#include<ctime>
using namespace std;
#define N 10
void LCSL(int m,int n,int *x,int *y,int **c,int **b);//计算最长公共子序列长度。
void LCS(int i,int j,int *x,int **b);//根据b[i][j]的内容打印......
在最坏情况下用「3/n-2」次比较找出a[0:n-1]中元素的最大值和最小值(2005-10-16 23:59:00)
摘要:【问题描述】
给定数组a[0:n-1],使设计一个算法,在最坏情况下用「3/n-2」次比较找出a[0:n-1]中元素的最大值和最小值。(《计算机算法设计与分析》,王晓东,2—15)
【算法设计】
1 5 8 2 3 9
5 8 9
8 9
9
求最小值设计与此类似,在此未画出图示。
【算法实现】
void SelectMaxAndMin(int *a,int *b,int n)
{
int j=1,s=1,i=1;
if(n==1) return;
......