拉斯维加斯算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//下一个皇后的编号 //在一列中,可以放置皇后的个数
while((k<=stopVegas)&&(count>0))
//1<=stop Vegas<=n
if(Place(k))
} if(count>0)
{ y[count++] = i; }
//随机位置
{ x[k++] = y[rnd.Random(count)]; } //count>0 表示放置成功
8后问题的LV算法中不同StopVegas值所相应的效率
StopVegas 0 1 p 1 1 s 114 39.63 e — — t 114 39.63
2
3 4 5
0.875
0.4931 0.2618 0.1624
22.53
13.48 10.31 9.33
39.67
15.10 8.79 7.29
8后问题的LV算法中不同StopVegas值所相应的效率
StopVegas 0 1 p 1 1 s 114 39.63 e — — t 114 39.63
2
3 4 5
0.875
0.4931 0.2618 0.1624
22.53
13.48 10.31 9.33
39.67
15.10 8.79 7.29
else {
退栈回溯到上一行,即i--; 移去该行已放置的皇后,以该皇后所在列的下一列作为当前列;
}
}
1
××
1
2 1 34
3 1 24
4 123
2 34
× ×
24 23 14 23 13 12 34 × 34 13 24 14 12 ×× 4 3 4 2× 3 2 4 3 4 1 3 1 4 2 41 21 3 2 31 2 1
bool Queen::QueensLv(int stopVegas) //随机放置n个皇后的拉斯维加斯算法
{
RandomNumber rnd; / /随机数产生器 int k = 1; int count = 1; { count = 0; for(int i=1; i<=n; i++) { x[k] = i; //位置
设t(x)是算法obstinate找到一个正确解所需的期望时间,则若 要最小化t(x),则需在p(x), s(x)和e(x)之间进行某种折衷。
t ( x) p( x) s ( x) (1 p( x))(e( x) t ( x)) LV 成功的概率 LV失败的概率 1 p ( x) e( x ) 解此方程可得:t ( x) s ( x) p ( x)
4 →╳
1
╳ ╳
5→1
╳
1 1 ╳
╳→1
╳
╳ ╳ ╳ ╳ ╳ ╳
╳
8 ╳ ╳ ╳ ╳ ╳
╳ ╳ ╳
6
6 →╳
╳
改进算法
QueensLV函数中: while((k<=n)&&(count>0))
改为
while((k<=stopVegas)&&(count>0))
nQueen函数中: while(!X.QueensLv(stopVegas)); //直到随机放好stopVegas个皇后 if(X. Backtrack(stop+1)) //算法的回溯搜索部分 { for(int i=1; i<=n; i++) cout<<p[i]<<" "; found=true; } stopVegas——控制随机放置皇后的个数,如何选择? 改进算法的试验结果:
};
2.3 拉斯维加斯算法的改进
问题?
消极:LV算法过于消极,一旦失败,从头再来。 乐观:回溯法过于乐观,一旦放置某个皇后失败,就进行 系统回退一步的策略,而这一步往往不一定有效。 折中:会更好吗?一般情况下为此。 先用LV方法随机地放置前若干个结点,例如 k 个。然后 使用回溯法放置后若干个结点,但不考虑重放前 k个结点。
2.1 回溯法(8后问题)
置当前行为第1行,当前列为第1列,即i←j←1; while i ≤ 8 do { // 当前行号≤ 8 检查当前行:从当前列 j 起向后逐列试探,寻找安全列号;
if 找到安全列号 then {
放置皇后,将列号记入栈,并将下一行置为当前行(i++); j←1; } //当前列置为1
p(x) —— 对于实例x,算法成功的概率 s(x) —— 算法求解成功时所需的期望时间 e(x) —— 算法求解失败时所需的期望时间
2. N后问题
对于n后问题的任何一个解而言,每一个皇后在棋盘上的位
置无任何规律,不具有系统性,而更象是随机放置的。由 此容易想到下面的拉斯维加斯算法。 纯LV算法求解思路 : 在棋盘上相继的各行中随机地放置皇后, 并注意使新放置的皇后与已放置的皇后互不攻击,直至n个 皇后均已相容地放置好,或已没有下一个皇后的可放置位 置时为止。 回溯法和 LV算法结合求解思路 : 如果将上述随机放置策略与 回溯法相结合,可能会获得更好的效果。可以先在棋盘的 若干行中随机地放置皇后,然后在后继行中用回溯法继续 放置,直至找到一个解或宣告失败。随机放置的皇后越多, 后继回溯搜索所需的时间就越少,但失败的概率也就越大。
拉斯维加斯(Las Vegas)算法
姓名:罗云加斯算法概述 N皇后问题
传统的回溯法
拉斯维加斯算法
拉斯维加斯算法的改进
整数因子分解
1. 拉斯维加斯算法概述
L·V 算法不会得到不正确的解。一旦用拉斯维加斯算法找到 一个解,这个解就一定是正确解。拉斯维加斯算法的一个 显著特征是它所作的随机性决策有可能导致算法找不到所 需的解。 算法的一般形式 LV(x, y, success) —— x是输入参数,y是返回问题的解, success是布尔值,true表示成功,false表示失败(说明未 得到解,那么可再次独立调用该算法,在时间允许的情况 一直运算到出解为止)。 p(x) —— 对于实例x,算法成功的概率 s(x) —— 算法求解成功时所需的期望时间 e(x) —— 算法求解失败时所需的期望时间
bool Queen::QueensLv(void) //随机放置n个皇后的拉斯维加斯算法
{
RandomNumber rnd; / /随机数产生器 int k = 1; int count = 1; { count = 0; for(int i=1; i<=n; i++) { x[k] = i; //位置
//测试皇后k置于第x[k]列的合法性
bool Queen::Place(int k) { for(int j=1; j<k; j++) { if((abs(k-j) == abs(x[j]-x[k])) || (x[j]==x[k])) { return false; } } return true; }
}
return (count>0);
bool nQueen(int n) //与回溯法结合解n后问题的拉斯维加斯算法 { Queen X; X.n = n; int *p = new int[n+1]; int *q = new int[n+1]; for(int i=0; i<=n; i++) { p[i] = 0; q[i] = 0; } X.y = p; X.x = q;
return (count>0);
void nQueen(int n) //解n后问题的拉斯维加斯算法 { Queen X; X.n = n; int *p = new int[n+1]; for(int i=0; i<=n; i++) { p[i] = 0; } X.x = p; X.y = new int[n+1];
int stop=5; bool found=false; if(n>15) stop=n-15;
while(!X.QueensLv(stop));
//直到放置成功
if(X. Backtrack(stop+1)) //算法的回溯搜索部分 { for(int i=1; i<=n; i++) cout<<p[i]<<" "; found=true; } cout<<endl; delete []p; delete []q; return found; }
28.20
29.01 35.10 46.92
6
7 8
0.1357
0.1293 0.1293
9.05
9 9
6.98
6.97 6.97
53.50
55.93 53.93
纯回溯时间:40ms stopVegas= 2 or 3:10ms(平均) 纯贪心LV:23ms(平均) 结论:一半略少的皇后随机放置较好。
若前面的随机选择位置不好,可能使得后面的位置不 成功,如若前两个皇后的位置是1、3。 随机放置的皇后越多,则后续回溯阶段的平均时间就 越少,失败的概率也就越大。
问题?
• 实例
1 1 1 1 1 1 7 1
1
1 ╳ ╳ 1 ╳ ╳
1
╳ 2 ╳ ╳ ╳ ╳
3
╳ ╳ ╳ ╳ ╳ ╳
1
╳ 1 4 ╳ ╳
//反复调用随机放置n个皇后的L·V算法,直到放置成功
}
while(!X.QueensLv()); for(int i=1; i<=n; i++) { cout<<p[i]<<" "; cout<<endl; delete []p;
}
int main() //主函数 { int n=8; cout<<n<<"皇后问题的解为:"<<endl; nQueen(n); return 0
bool Queen::Backtrack(int t) {
//解n后问题的回溯法
if(t>n)
{ for(int i=1; i<=n; i++) { y[i] = x[i]; } return true; } else //问题的解
{
for(int i=1; i<=n; i++) { x[t] = i;
if(Place(t)&&Backtrack(t+1))
{ return true; } } } return false;
3.1 整数因子分解
问题描述
设n>1是一个整数。关于整数n的因子分解问题是找出n的如下 形式的唯一分解式:
其中,p1<p2<…<pk是k个素数,m1,m2,…,mk是k个正整数。 如果n是一个合数,则n必有一个非平凡因子x,1<x<n,使得 x可以整除n。给定一个合数n,求n的一个非平凡因子的问题 称为整数n的因子分割问题。
解题思路
整数因子分解最直观的方法当数“试除法”,数论中的 Mertens定理告诉我们76%的奇数都有小于100的素因子,因此 对于大多数整数,“试除法”已经足够,但是对于特殊的数, 特别是素因子普遍较大的时候,“试除法"的效率便明显不足。 和素数检验类似,目前几乎所有实用的分解方法都是概率性 的算法, 目标是找到能计算x 的算法, 使得(x,N) > 1 的概 率较大(而最大公因子可以很快地计算).
一个正确的LV算法,要求对每个实例x, p(x)>0,更好的 情况是:
常数 0, p( x)
void obstinate(Object x, Object y) { // 反复调用拉斯维加斯算法LV(x,y),直到找到问题的一个解y bool success= false; while (!success) success=lv(x,y); }
28.20
29.01 35.10 46.92
6
7 8
0.1357
0.1293 0.1293
9.05
9 9
6.98
6.97 6.97
53.50
55.93 53.93
p:算法成功的概率 s:一次成功搜索访问的节点数平均值 e:一次不成功搜索访问的节点数平均值 t:最终找到一个解所访问的节点数的平均值
t=s+(1-p)e/p
√ √
2.2 拉斯维加斯算法(8后问题)
实例
1 1 1 ╳ 1 1 ╳ 2 1 3 ╳ ╳ 1 1 ╳ 1 1 1 ╳ ╳ 1 ╳ 1 1 7 ╳ ╳ ╳ 1 ╳ 8 ╳
╳
1 ╳ ╳
╳
╳ ╳ ╳
╳
╳ ╳ ╳
1
╳ ╳ 4
5
╳ ╳ ╳
╳
╳ 6 ╳
╳
╳ ╳ ╳
╳
╳ ╳ ╳
2.2 拉斯维加斯算法
class Queen { friend void nQueen(int); private: bool Place(int k); //测试皇后k置于第x[k]列的合法性 bool QueensLv(void); //随机放置n个皇后拉斯维加斯算法 int n; //皇后个数 int *x,*y; //解向量 };
//下一个皇后的编号 //在一列中,可以放置皇后的个数
while((k<=n)&&(count>0))
if(Place(k))
} if(count>0) {
{
y[count++] = i;
}
}
//随机位置
x[k++] = y[rnd.Random(count)]; //count>0 表示放置成功
}
while((k<=stopVegas)&&(count>0))
//1<=stop Vegas<=n
if(Place(k))
} if(count>0)
{ y[count++] = i; }
//随机位置
{ x[k++] = y[rnd.Random(count)]; } //count>0 表示放置成功
8后问题的LV算法中不同StopVegas值所相应的效率
StopVegas 0 1 p 1 1 s 114 39.63 e — — t 114 39.63
2
3 4 5
0.875
0.4931 0.2618 0.1624
22.53
13.48 10.31 9.33
39.67
15.10 8.79 7.29
8后问题的LV算法中不同StopVegas值所相应的效率
StopVegas 0 1 p 1 1 s 114 39.63 e — — t 114 39.63
2
3 4 5
0.875
0.4931 0.2618 0.1624
22.53
13.48 10.31 9.33
39.67
15.10 8.79 7.29
else {
退栈回溯到上一行,即i--; 移去该行已放置的皇后,以该皇后所在列的下一列作为当前列;
}
}
1
××
1
2 1 34
3 1 24
4 123
2 34
× ×
24 23 14 23 13 12 34 × 34 13 24 14 12 ×× 4 3 4 2× 3 2 4 3 4 1 3 1 4 2 41 21 3 2 31 2 1
bool Queen::QueensLv(int stopVegas) //随机放置n个皇后的拉斯维加斯算法
{
RandomNumber rnd; / /随机数产生器 int k = 1; int count = 1; { count = 0; for(int i=1; i<=n; i++) { x[k] = i; //位置
设t(x)是算法obstinate找到一个正确解所需的期望时间,则若 要最小化t(x),则需在p(x), s(x)和e(x)之间进行某种折衷。
t ( x) p( x) s ( x) (1 p( x))(e( x) t ( x)) LV 成功的概率 LV失败的概率 1 p ( x) e( x ) 解此方程可得:t ( x) s ( x) p ( x)
4 →╳
1
╳ ╳
5→1
╳
1 1 ╳
╳→1
╳
╳ ╳ ╳ ╳ ╳ ╳
╳
8 ╳ ╳ ╳ ╳ ╳
╳ ╳ ╳
6
6 →╳
╳
改进算法
QueensLV函数中: while((k<=n)&&(count>0))
改为
while((k<=stopVegas)&&(count>0))
nQueen函数中: while(!X.QueensLv(stopVegas)); //直到随机放好stopVegas个皇后 if(X. Backtrack(stop+1)) //算法的回溯搜索部分 { for(int i=1; i<=n; i++) cout<<p[i]<<" "; found=true; } stopVegas——控制随机放置皇后的个数,如何选择? 改进算法的试验结果:
};
2.3 拉斯维加斯算法的改进
问题?
消极:LV算法过于消极,一旦失败,从头再来。 乐观:回溯法过于乐观,一旦放置某个皇后失败,就进行 系统回退一步的策略,而这一步往往不一定有效。 折中:会更好吗?一般情况下为此。 先用LV方法随机地放置前若干个结点,例如 k 个。然后 使用回溯法放置后若干个结点,但不考虑重放前 k个结点。
2.1 回溯法(8后问题)
置当前行为第1行,当前列为第1列,即i←j←1; while i ≤ 8 do { // 当前行号≤ 8 检查当前行:从当前列 j 起向后逐列试探,寻找安全列号;
if 找到安全列号 then {
放置皇后,将列号记入栈,并将下一行置为当前行(i++); j←1; } //当前列置为1
p(x) —— 对于实例x,算法成功的概率 s(x) —— 算法求解成功时所需的期望时间 e(x) —— 算法求解失败时所需的期望时间
2. N后问题
对于n后问题的任何一个解而言,每一个皇后在棋盘上的位
置无任何规律,不具有系统性,而更象是随机放置的。由 此容易想到下面的拉斯维加斯算法。 纯LV算法求解思路 : 在棋盘上相继的各行中随机地放置皇后, 并注意使新放置的皇后与已放置的皇后互不攻击,直至n个 皇后均已相容地放置好,或已没有下一个皇后的可放置位 置时为止。 回溯法和 LV算法结合求解思路 : 如果将上述随机放置策略与 回溯法相结合,可能会获得更好的效果。可以先在棋盘的 若干行中随机地放置皇后,然后在后继行中用回溯法继续 放置,直至找到一个解或宣告失败。随机放置的皇后越多, 后继回溯搜索所需的时间就越少,但失败的概率也就越大。
拉斯维加斯(Las Vegas)算法
姓名:罗云加斯算法概述 N皇后问题
传统的回溯法
拉斯维加斯算法
拉斯维加斯算法的改进
整数因子分解
1. 拉斯维加斯算法概述
L·V 算法不会得到不正确的解。一旦用拉斯维加斯算法找到 一个解,这个解就一定是正确解。拉斯维加斯算法的一个 显著特征是它所作的随机性决策有可能导致算法找不到所 需的解。 算法的一般形式 LV(x, y, success) —— x是输入参数,y是返回问题的解, success是布尔值,true表示成功,false表示失败(说明未 得到解,那么可再次独立调用该算法,在时间允许的情况 一直运算到出解为止)。 p(x) —— 对于实例x,算法成功的概率 s(x) —— 算法求解成功时所需的期望时间 e(x) —— 算法求解失败时所需的期望时间
bool Queen::QueensLv(void) //随机放置n个皇后的拉斯维加斯算法
{
RandomNumber rnd; / /随机数产生器 int k = 1; int count = 1; { count = 0; for(int i=1; i<=n; i++) { x[k] = i; //位置
//测试皇后k置于第x[k]列的合法性
bool Queen::Place(int k) { for(int j=1; j<k; j++) { if((abs(k-j) == abs(x[j]-x[k])) || (x[j]==x[k])) { return false; } } return true; }
}
return (count>0);
bool nQueen(int n) //与回溯法结合解n后问题的拉斯维加斯算法 { Queen X; X.n = n; int *p = new int[n+1]; int *q = new int[n+1]; for(int i=0; i<=n; i++) { p[i] = 0; q[i] = 0; } X.y = p; X.x = q;
return (count>0);
void nQueen(int n) //解n后问题的拉斯维加斯算法 { Queen X; X.n = n; int *p = new int[n+1]; for(int i=0; i<=n; i++) { p[i] = 0; } X.x = p; X.y = new int[n+1];
int stop=5; bool found=false; if(n>15) stop=n-15;
while(!X.QueensLv(stop));
//直到放置成功
if(X. Backtrack(stop+1)) //算法的回溯搜索部分 { for(int i=1; i<=n; i++) cout<<p[i]<<" "; found=true; } cout<<endl; delete []p; delete []q; return found; }
28.20
29.01 35.10 46.92
6
7 8
0.1357
0.1293 0.1293
9.05
9 9
6.98
6.97 6.97
53.50
55.93 53.93
纯回溯时间:40ms stopVegas= 2 or 3:10ms(平均) 纯贪心LV:23ms(平均) 结论:一半略少的皇后随机放置较好。
若前面的随机选择位置不好,可能使得后面的位置不 成功,如若前两个皇后的位置是1、3。 随机放置的皇后越多,则后续回溯阶段的平均时间就 越少,失败的概率也就越大。
问题?
• 实例
1 1 1 1 1 1 7 1
1
1 ╳ ╳ 1 ╳ ╳
1
╳ 2 ╳ ╳ ╳ ╳
3
╳ ╳ ╳ ╳ ╳ ╳
1
╳ 1 4 ╳ ╳
//反复调用随机放置n个皇后的L·V算法,直到放置成功
}
while(!X.QueensLv()); for(int i=1; i<=n; i++) { cout<<p[i]<<" "; cout<<endl; delete []p;
}
int main() //主函数 { int n=8; cout<<n<<"皇后问题的解为:"<<endl; nQueen(n); return 0
bool Queen::Backtrack(int t) {
//解n后问题的回溯法
if(t>n)
{ for(int i=1; i<=n; i++) { y[i] = x[i]; } return true; } else //问题的解
{
for(int i=1; i<=n; i++) { x[t] = i;
if(Place(t)&&Backtrack(t+1))
{ return true; } } } return false;
3.1 整数因子分解
问题描述
设n>1是一个整数。关于整数n的因子分解问题是找出n的如下 形式的唯一分解式:
其中,p1<p2<…<pk是k个素数,m1,m2,…,mk是k个正整数。 如果n是一个合数,则n必有一个非平凡因子x,1<x<n,使得 x可以整除n。给定一个合数n,求n的一个非平凡因子的问题 称为整数n的因子分割问题。
解题思路
整数因子分解最直观的方法当数“试除法”,数论中的 Mertens定理告诉我们76%的奇数都有小于100的素因子,因此 对于大多数整数,“试除法”已经足够,但是对于特殊的数, 特别是素因子普遍较大的时候,“试除法"的效率便明显不足。 和素数检验类似,目前几乎所有实用的分解方法都是概率性 的算法, 目标是找到能计算x 的算法, 使得(x,N) > 1 的概 率较大(而最大公因子可以很快地计算).
一个正确的LV算法,要求对每个实例x, p(x)>0,更好的 情况是:
常数 0, p( x)
void obstinate(Object x, Object y) { // 反复调用拉斯维加斯算法LV(x,y),直到找到问题的一个解y bool success= false; while (!success) success=lv(x,y); }
28.20
29.01 35.10 46.92
6
7 8
0.1357
0.1293 0.1293
9.05
9 9
6.98
6.97 6.97
53.50
55.93 53.93
p:算法成功的概率 s:一次成功搜索访问的节点数平均值 e:一次不成功搜索访问的节点数平均值 t:最终找到一个解所访问的节点数的平均值
t=s+(1-p)e/p
√ √
2.2 拉斯维加斯算法(8后问题)
实例
1 1 1 ╳ 1 1 ╳ 2 1 3 ╳ ╳ 1 1 ╳ 1 1 1 ╳ ╳ 1 ╳ 1 1 7 ╳ ╳ ╳ 1 ╳ 8 ╳
╳
1 ╳ ╳
╳
╳ ╳ ╳
╳
╳ ╳ ╳
1
╳ ╳ 4
5
╳ ╳ ╳
╳
╳ 6 ╳
╳
╳ ╳ ╳
╳
╳ ╳ ╳
2.2 拉斯维加斯算法
class Queen { friend void nQueen(int); private: bool Place(int k); //测试皇后k置于第x[k]列的合法性 bool QueensLv(void); //随机放置n个皇后拉斯维加斯算法 int n; //皇后个数 int *x,*y; //解向量 };
//下一个皇后的编号 //在一列中,可以放置皇后的个数
while((k<=n)&&(count>0))
if(Place(k))
} if(count>0) {
{
y[count++] = i;
}
}
//随机位置
x[k++] = y[rnd.Random(count)]; //count>0 表示放置成功
}