递归算法的优缺点
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if (i > n) { for (int j = 1; j <= n; j++) bestx[j] = x[j]; bestf = f; }
else for (int j = i; j <= n; j++) { f1+=M[x[j]][1];
f2[i]=((f2[i-1]>f1)?f2[i-1]:f1)+M[x[j]][2];
单源最短路径问题: void shortestpaths(v)
{ MinHeap H[1000];
//定义最小堆 MinHeapNode<type> E; E.i=v; E.length=0; Dist[v]=0; //搜索问题界空间 while(true) { for(j=1;j<=n;j++) if((c[E.i][j]<inf)&&
线性规划基本定理:如果线性规划问题有最优解,则必有一基本可行最优解。 单纯形算法的特点是: (1)只对约束条件的若干组合进行测试,测试的每一步都使目标函数的值增加; (2)一般经过不大于 m 或 n 次迭代就可求得最优解。
单纯形算法的基本思想就是从一个基本可行解出发,进行一系列的基本可行解的变换。每次 变换将一个非基本变量与一个基本变量互调位置,且保持当前的线性规划问题是一个与原问
回溯算法解 0-1 背包问题(解空间:子集树): template<class Typew, class Typep> Typep Knap<Typew, Typep>::Bound(int i) {// 计算上界
Typew cleft = c - cw; // 剩余容量 Typep b = cp; // 以物品单位重量价值递减序装入物品 while (i <= n && w[i] <= cleft) {
以比较为基础的排序算法的最坏倩况时间复杂性下界为 0(n·log2n)。
回溯法以深度优先的方式搜索解空间树 T,而分支限界法则以广度优先或以最小耗费优先的 方式搜索解空间树 T。
舍伍德算法设计的基本思想: 设 A 是一个确定性算法,当它的输入实例为 x 时所需的计算时间记为 tA(x)。设 Xn 是
回溯算法解批处理作业调度(解空间:排列 树):
f+=f2[i]; if (f < bestf) {
Swap(x[i], x[j]); Backtrack(i+1); Swap(x[i], x[j]); } f1- =M[x[j]][1]; f- =f2[i]; } } 所以在最坏的情况下,整个算法的计算时间 复杂性为 O(n!)
①图 G 的每个顶点对应于 f 中的每个文字(多次出现的重复计算)。 ②若 G 中两个顶点其原对应的文字不相互补且不出现于同一于句中,则将其连线。
设 f 有 n 个子句,则 f 可满足当且仅当 f 对应的图 G 中有 n 个顶点的团。 这是因为: (a)若 f 可满足,即有某种赋值使得 f 取值为真,它等价于使得每个 ci 中都至少有一个文字为 真,这 n 个文字(每个 ci(1<i<n)中一个)对应的图 G 中的 n 个顶点就构成一个团。 (b)若图 G 中有一 n 个顶点的团,则取给出使得这 n 个顶点对应的文字都为真的赋值,则 f 的取值为真(这由图 G 的定义易证)。 显见,上述构造图 G 的方法是多项式界的,因此 SAT 团问题。 由(a)、(b)有,团问题 NPC。证毕。
if (t>n) { sum++; for (int i=1; i<=n; i++) cout << x[i] << ' '; cout << endl; } else for (int i=1;i<=m;i++) {
x[t]=i; if (Ok(t)) Backtrack(t+1); } } bool Color::Ok(int k) {// 检查颜色可用性 for (int j=1;j<=n;j++) if ((a[k][j]==1)&&(x[j]==x[k])) return false; return true;
Type Minout[N+1]; //计算 Minout[i]=顶点 i 的最小出边费 用 Type Minsurn=0;//最小出边费用和 for(i=1;i<=n;i++){
Min=NoEdge; for( j=1;j<=n;j++)
if(a[i][j]!=NoEdge&&(a[i][j]<Min || Min==NoEdge) Min=a[i][j];
if ( bound(i+1)>bestp ) backtrack(i+1); //x[i]=0
} 由于上界函数 Bound()需要 O(n)的时间,在 最坏的情况下有 O(2n)个右儿子结点需要计 算上界函数,所以 0-1 背包问题的回溯算法 Backtrack()所需要的时间是 O(n2n)。
回溯算法解图的 m 着色问题: void Color::Backtrack(int t) {
v[i+ 1]=E.x[i]; while (true){ //释放最小堆中所有结点
delete(H, E. x); DeleteMin(H,E);} //取下一扩展结点 if (堆已空) break; //堆已空
}
.
.
return(bestc); } void Flowshop::Backtrack(int i) {
.
递归算法的优缺点: ○1 优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计 算法、调试程序带来很大方便。 ○2 缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归 算法要多。
边界条件与递归方程是递归函数的二个要素
应用分治法的两个前提是问题的可分性和解的可归并性
cleft -= w[i]; b += p[i]; i++; } // 装满背包 if (i <= n) b += p[i]/w[i] * cleft; return b; } void backtrack(i)
{ if( i>n ) { bestp=cp; return; }
if(cw+w[i]<=c)//x[i]=1 { cw+=w[i] ;cp+=p[i]; backtrack(i+1); cw-=w[i] ;cp-=p[i]; }
}来自百度文库
} delete(H,E.x); }//完成结点扩展 DeleteMin(H,E);} //取下一扩展结点
if (堆已空) break; //堆已空
} if(bestc==NoEdge)return( NoEdge); //无回路 //将最优解复制到 v[l:n] for(i=0;i<n;i++)
具体实例 x 求解成功或求解失败所需的平均时间,则有:t(x) p(x)s(x) (1 p(x))(e(x) t(x))
解此方程可得:
t( x)
s( x)
1
p( x) e( x)
p( x)
蒙特卡罗(Monte Carlo)算法的基本思想: 设 p 是一个实数,且 1/2<p<1。如果一个蒙特卡罗算法对于问题的任一实例得到正确解的概 率不小于 p,则称该蒙特卡罗算法是 p 正确的,且称 p-1/2 是该算法的优势。 如果对于同一实例,蒙特卡罗算法不会给出 2 个不同的正确解答,则称该蒙特卡罗算法是一 致的。
.
.
题完全等价的标准线性规划问题。
图灵机由以下几部分组成:一条无限长的带(有无穷个格子)、一个读写头、一个有限状态 控制器以及一个程序。
NPC 形式化定义: 定义 1:语言 L 是 NP 完全的当且仅当(1) L【NP;(2)对于所有 L’【NP 有 L’ ~pL。
如果有一个语言 L 满足上述性质(2),但不一定满足性质(1),则称该语言是 NP 难的。 所有 NP 完全语言构成的语言类称为 NP 完全语言类,就是 NPC。
算法 A 的输入规模为 n 的实例的全体,则当问题的输入规模为 n 时,算法 A 所需的平均时
间为 t A (n) t A (x) / | X n | xX n
这显然不能排除存在 x∈Xn 使得t A ( x) t A (n) 的可能性。希望获得一个随机化算法 B,使得对问题的输入规模为 n 的每一个实例均有 t B ( x) t A (n) s(n)
拉斯维加斯( Las Vegas )算法的基本思想:
设 p(x)是对输入 x 调用拉斯维加斯算法获得问题的一个解的概率。一个正确的拉斯维加斯算
法应该对所有输入 x 均有 p(x)>0。
设 t(x)是算法 obstinate 找到具体实例 x 的一个解所需的平均时间 ,s(x)和 e(x)分别是算法对于
Type b=cc+rcost; //下界 if(b< bestc||bestc== NoEdge )
{ //子树可能含最优解 for(j= 0; j< n; j++) N.x[j]=E.x[j];
N.x[E.s+1]=E.x[i]; N.x[i]=E.x[E.s+1]; N.cc=cc; N.s= E.s+1; N.lcost=b; N.rcost=rcost; Insert(H,N);
a[E.x[n-2]][E.x[n-1]]+a[E.x[n-1]][1]< bestc || bestc==NoEdge){
//费用更小的回路
bestc=Ecc+a[E.x[n-2]][E.x[n-1]] +a[E.x[n-1]][1];
E.c=bestc; E.lcost=bestc; E.s++;
(E.length+c[E.i][j]<dist[j])) {dist[j]=E.length+c[E.i][j];
prev[j]=E.i; //加入活结点优先队列 MinHeapNode <type> N; N.i=j; N.length=dist[j]; H.Insert(N); } //取下一个扩展结点 try { H.DeleteMin(E); } //优先队列为空 catch (OutOfBounds) {break;} } }
if(Min==NoEdge) return(NoEdge); //无回路
MinOut[i]= Min; MinSum+=Min;
} //初始化
MinHeapNode E; for(i= 0;i< n;i++)
E.x[i]= i+ 1; E.s=0; E.cc=0; E.rcost=MinSum; Bestc=NoEdge; while(E.s<n-1) //非叶结点 if(E.s<n-1){ //当前扩展结点是叶结点的父 结点 if ( a[E.x[n-2][E.x[n-1]]!=NoEdge & & a[E.x[n-2][1]!=NoEdge&&(E.cc+
.
.
(1)数值随机化算法: 求解数值问题,得到近似解 (2)Monte Carlo 算法: 问题准确性,但却无法确定解正确性 (3)Las Vegas 算法: 获得正确解,但存在找不到解的可能性 (4)Sherwood 算法: 保证能获得正确解
旅行售货员问题:(优先队列式分支限界法)
Type Travding (int v[]) { MinHeapNode H(1000);
.
.
}
回溯法总的时间耗费是 O(m^n *n)
回溯算法解最大团问题(解空间:子集树):
void Clique::Backtrack(int i) {// 计算最大团
Insert(H,E);} else delete(E.x) ;} //舍弃扩展结点 else { //产生当前扩展结点的儿子结点 for( i=E.s+1;i<n;i++=
if(a[E.x[E.s]][E.x[i]]!=NoEdge) { //可行儿子结点
Type cc=E.cc+a[E.x[E.s]][E.x[i]]; Type rcost=E.rcost-MinOut[E.x[E.s]];
定理 1 设 L 是 NP 完全的,则(1)L P 当且仅当 P=NP;(2)若 L p L1,且 L1 NP, 则 L1 是 NP 完全的。
团问题: 任给图 G 和整数 k.试判定图 G 中是否存在具有 k 个顶点的团? 1)团问题 NP。显然,验证 G 的一个子图是否成团只需多项式时间即可。 2)SAT 团问题。 任给表达式 f.构造一个相应的图 G 如下:
else for (int j = i; j <= n; j++) { f1+=M[x[j]][1];
f2[i]=((f2[i-1]>f1)?f2[i-1]:f1)+M[x[j]][2];
单源最短路径问题: void shortestpaths(v)
{ MinHeap H[1000];
//定义最小堆 MinHeapNode<type> E; E.i=v; E.length=0; Dist[v]=0; //搜索问题界空间 while(true) { for(j=1;j<=n;j++) if((c[E.i][j]<inf)&&
线性规划基本定理:如果线性规划问题有最优解,则必有一基本可行最优解。 单纯形算法的特点是: (1)只对约束条件的若干组合进行测试,测试的每一步都使目标函数的值增加; (2)一般经过不大于 m 或 n 次迭代就可求得最优解。
单纯形算法的基本思想就是从一个基本可行解出发,进行一系列的基本可行解的变换。每次 变换将一个非基本变量与一个基本变量互调位置,且保持当前的线性规划问题是一个与原问
回溯算法解 0-1 背包问题(解空间:子集树): template<class Typew, class Typep> Typep Knap<Typew, Typep>::Bound(int i) {// 计算上界
Typew cleft = c - cw; // 剩余容量 Typep b = cp; // 以物品单位重量价值递减序装入物品 while (i <= n && w[i] <= cleft) {
以比较为基础的排序算法的最坏倩况时间复杂性下界为 0(n·log2n)。
回溯法以深度优先的方式搜索解空间树 T,而分支限界法则以广度优先或以最小耗费优先的 方式搜索解空间树 T。
舍伍德算法设计的基本思想: 设 A 是一个确定性算法,当它的输入实例为 x 时所需的计算时间记为 tA(x)。设 Xn 是
回溯算法解批处理作业调度(解空间:排列 树):
f+=f2[i]; if (f < bestf) {
Swap(x[i], x[j]); Backtrack(i+1); Swap(x[i], x[j]); } f1- =M[x[j]][1]; f- =f2[i]; } } 所以在最坏的情况下,整个算法的计算时间 复杂性为 O(n!)
①图 G 的每个顶点对应于 f 中的每个文字(多次出现的重复计算)。 ②若 G 中两个顶点其原对应的文字不相互补且不出现于同一于句中,则将其连线。
设 f 有 n 个子句,则 f 可满足当且仅当 f 对应的图 G 中有 n 个顶点的团。 这是因为: (a)若 f 可满足,即有某种赋值使得 f 取值为真,它等价于使得每个 ci 中都至少有一个文字为 真,这 n 个文字(每个 ci(1<i<n)中一个)对应的图 G 中的 n 个顶点就构成一个团。 (b)若图 G 中有一 n 个顶点的团,则取给出使得这 n 个顶点对应的文字都为真的赋值,则 f 的取值为真(这由图 G 的定义易证)。 显见,上述构造图 G 的方法是多项式界的,因此 SAT 团问题。 由(a)、(b)有,团问题 NPC。证毕。
if (t>n) { sum++; for (int i=1; i<=n; i++) cout << x[i] << ' '; cout << endl; } else for (int i=1;i<=m;i++) {
x[t]=i; if (Ok(t)) Backtrack(t+1); } } bool Color::Ok(int k) {// 检查颜色可用性 for (int j=1;j<=n;j++) if ((a[k][j]==1)&&(x[j]==x[k])) return false; return true;
Type Minout[N+1]; //计算 Minout[i]=顶点 i 的最小出边费 用 Type Minsurn=0;//最小出边费用和 for(i=1;i<=n;i++){
Min=NoEdge; for( j=1;j<=n;j++)
if(a[i][j]!=NoEdge&&(a[i][j]<Min || Min==NoEdge) Min=a[i][j];
if ( bound(i+1)>bestp ) backtrack(i+1); //x[i]=0
} 由于上界函数 Bound()需要 O(n)的时间,在 最坏的情况下有 O(2n)个右儿子结点需要计 算上界函数,所以 0-1 背包问题的回溯算法 Backtrack()所需要的时间是 O(n2n)。
回溯算法解图的 m 着色问题: void Color::Backtrack(int t) {
v[i+ 1]=E.x[i]; while (true){ //释放最小堆中所有结点
delete(H, E. x); DeleteMin(H,E);} //取下一扩展结点 if (堆已空) break; //堆已空
}
.
.
return(bestc); } void Flowshop::Backtrack(int i) {
.
递归算法的优缺点: ○1 优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计 算法、调试程序带来很大方便。 ○2 缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归 算法要多。
边界条件与递归方程是递归函数的二个要素
应用分治法的两个前提是问题的可分性和解的可归并性
cleft -= w[i]; b += p[i]; i++; } // 装满背包 if (i <= n) b += p[i]/w[i] * cleft; return b; } void backtrack(i)
{ if( i>n ) { bestp=cp; return; }
if(cw+w[i]<=c)//x[i]=1 { cw+=w[i] ;cp+=p[i]; backtrack(i+1); cw-=w[i] ;cp-=p[i]; }
}来自百度文库
} delete(H,E.x); }//完成结点扩展 DeleteMin(H,E);} //取下一扩展结点
if (堆已空) break; //堆已空
} if(bestc==NoEdge)return( NoEdge); //无回路 //将最优解复制到 v[l:n] for(i=0;i<n;i++)
具体实例 x 求解成功或求解失败所需的平均时间,则有:t(x) p(x)s(x) (1 p(x))(e(x) t(x))
解此方程可得:
t( x)
s( x)
1
p( x) e( x)
p( x)
蒙特卡罗(Monte Carlo)算法的基本思想: 设 p 是一个实数,且 1/2<p<1。如果一个蒙特卡罗算法对于问题的任一实例得到正确解的概 率不小于 p,则称该蒙特卡罗算法是 p 正确的,且称 p-1/2 是该算法的优势。 如果对于同一实例,蒙特卡罗算法不会给出 2 个不同的正确解答,则称该蒙特卡罗算法是一 致的。
.
.
题完全等价的标准线性规划问题。
图灵机由以下几部分组成:一条无限长的带(有无穷个格子)、一个读写头、一个有限状态 控制器以及一个程序。
NPC 形式化定义: 定义 1:语言 L 是 NP 完全的当且仅当(1) L【NP;(2)对于所有 L’【NP 有 L’ ~pL。
如果有一个语言 L 满足上述性质(2),但不一定满足性质(1),则称该语言是 NP 难的。 所有 NP 完全语言构成的语言类称为 NP 完全语言类,就是 NPC。
算法 A 的输入规模为 n 的实例的全体,则当问题的输入规模为 n 时,算法 A 所需的平均时
间为 t A (n) t A (x) / | X n | xX n
这显然不能排除存在 x∈Xn 使得t A ( x) t A (n) 的可能性。希望获得一个随机化算法 B,使得对问题的输入规模为 n 的每一个实例均有 t B ( x) t A (n) s(n)
拉斯维加斯( Las Vegas )算法的基本思想:
设 p(x)是对输入 x 调用拉斯维加斯算法获得问题的一个解的概率。一个正确的拉斯维加斯算
法应该对所有输入 x 均有 p(x)>0。
设 t(x)是算法 obstinate 找到具体实例 x 的一个解所需的平均时间 ,s(x)和 e(x)分别是算法对于
Type b=cc+rcost; //下界 if(b< bestc||bestc== NoEdge )
{ //子树可能含最优解 for(j= 0; j< n; j++) N.x[j]=E.x[j];
N.x[E.s+1]=E.x[i]; N.x[i]=E.x[E.s+1]; N.cc=cc; N.s= E.s+1; N.lcost=b; N.rcost=rcost; Insert(H,N);
a[E.x[n-2]][E.x[n-1]]+a[E.x[n-1]][1]< bestc || bestc==NoEdge){
//费用更小的回路
bestc=Ecc+a[E.x[n-2]][E.x[n-1]] +a[E.x[n-1]][1];
E.c=bestc; E.lcost=bestc; E.s++;
(E.length+c[E.i][j]<dist[j])) {dist[j]=E.length+c[E.i][j];
prev[j]=E.i; //加入活结点优先队列 MinHeapNode <type> N; N.i=j; N.length=dist[j]; H.Insert(N); } //取下一个扩展结点 try { H.DeleteMin(E); } //优先队列为空 catch (OutOfBounds) {break;} } }
if(Min==NoEdge) return(NoEdge); //无回路
MinOut[i]= Min; MinSum+=Min;
} //初始化
MinHeapNode E; for(i= 0;i< n;i++)
E.x[i]= i+ 1; E.s=0; E.cc=0; E.rcost=MinSum; Bestc=NoEdge; while(E.s<n-1) //非叶结点 if(E.s<n-1){ //当前扩展结点是叶结点的父 结点 if ( a[E.x[n-2][E.x[n-1]]!=NoEdge & & a[E.x[n-2][1]!=NoEdge&&(E.cc+
.
.
(1)数值随机化算法: 求解数值问题,得到近似解 (2)Monte Carlo 算法: 问题准确性,但却无法确定解正确性 (3)Las Vegas 算法: 获得正确解,但存在找不到解的可能性 (4)Sherwood 算法: 保证能获得正确解
旅行售货员问题:(优先队列式分支限界法)
Type Travding (int v[]) { MinHeapNode H(1000);
.
.
}
回溯法总的时间耗费是 O(m^n *n)
回溯算法解最大团问题(解空间:子集树):
void Clique::Backtrack(int i) {// 计算最大团
Insert(H,E);} else delete(E.x) ;} //舍弃扩展结点 else { //产生当前扩展结点的儿子结点 for( i=E.s+1;i<n;i++=
if(a[E.x[E.s]][E.x[i]]!=NoEdge) { //可行儿子结点
Type cc=E.cc+a[E.x[E.s]][E.x[i]]; Type rcost=E.rcost-MinOut[E.x[E.s]];
定理 1 设 L 是 NP 完全的,则(1)L P 当且仅当 P=NP;(2)若 L p L1,且 L1 NP, 则 L1 是 NP 完全的。
团问题: 任给图 G 和整数 k.试判定图 G 中是否存在具有 k 个顶点的团? 1)团问题 NP。显然,验证 G 的一个子图是否成团只需多项式时间即可。 2)SAT 团问题。 任给表达式 f.构造一个相应的图 G 如下: