ch4 Las Vegas 算法
特点:有找不到解的风险,智慧返回正确的解,成功的概率随着执行时间的增加而增加
与sherwood算法比较:sherwood算法的平均性能不一定而且可以计算出一个给定实例的执行上界
lv算法更有效率,但是时间的上界可能不存在
形式 LV(x,y,success)输入实例,返回参数,是否成功
4.1 八皇后问题
回溯法:
i=j=1;
while i<8 do {//当前行号i<=8
检查当前行i:从当前列j起向后逐列试探,寻找安全列号;
if 找到安全的列号 then{
放置皇后,将列号记入栈内,将下一行置为当前行i++
j=1;//当前列置为1
}else{
退栈回到上一行,i--;
移去该行已经放置的黄根后,以该皇后所在列的下一列为当前列;
}
}
LV算法:
try[i]表示第i个皇后放在(i,try[i])位置上
安全位置:try[i]-try[j] != {i-j,0,j=i}//无行冲突,列冲突以及对角线冲突
Queen(success){//贪心的lv算法,所有的皇后都是随机放置
//如果success=true, 则try[1..8]包含8后问题的一个解
col,diag45,diag135=空;//列以及两个对角线集合对的初值为空
k=0;//行号
repeat//已经放置好k个皇后,考虑放第k+1个皇后
nb=0;//计数器,nb值为(k+1)个皇后的open位置总数
for i=1 to 8 do{//i为列号,试探(k+1,i)是否安全
if (i not in col) and (i-k-1 not in diag45) and (i+k+1 not in diag135) then{
//i列对与k+1皇后可用的,但是不着急把皇后放在第i列
nb=nb+1;
if uniform(1..nb)=1 then//或许放在第i列
j=i//注意第一次uniform一定返回1,则j一定有值i
}//end if
}//end for,在nb个安全位置上随机选择1个位置j放置
if(nb>0) then{
k=k+1;
try[k]=j;
col =col+{j};
diag45=diag45+{j-k};
diag135=diag135+{j+k};
}//end if
until (nb==0) or (k==8)
success=(nb>0);
}
LV算法改进:
将最后两行改为:
until nb=0 or k=stepVegas;
if(nb>0) then//已经随机放好stepVegas个皇后
backtrace(k,col,diag45,diag135,success);
else
success = false
ps:一般来说一半使用随机,一半使用回溯法是比较好的
4.2 模p平方根
4.3 整数的因数分解
MC算法可以用来判定n是否为素数
split(n) -> n为合数时找到n的一个非平凡的因数
1)朴素的split算法
split(n){
//n为素数,返回1,否则返回找到的n的最小非平凡因数
for i=2 to 根号n的下整数 do {
if (n mod i)=0 then
return i;//i>=2
}
return 1;//返回平凡因数
}
2)Dixon因数分解算法
基本思想:找到两个与n互素的整数a,b,使a^2=b^2(mod n)
n|(a^2-b^2) n|(a+b)(a-b)
如果n不满足n|(a+b),n|(a-b),则存在n的一个非平凡因子x满足
x|(a+b),(n/x)|(a-b)
则n和a+b的最大共因子是n的一个非平凡因子
Dixon(n,x,success){//找到合数n的某一个非平凡因子
if n is even then{
x=2;
success=true;
}else{
for i=2 to log(3)n do
if n^(1/i)为整数then{
x=n^(1/i);
success=true;
return;
}//n为合数且为奇数,并且至少有2个不同的奇素数因子
a,b 为是a^2=b^2(mod n)的整数
if a==+-b(mod n) then success=false
else{
x=gcd(a+b,n);
success=true;
}
}
}
第一步:在1到n-1之间随机选择x
第二步:在k+1个灯饰中找到一个非空子集,使相应的因数分解的积中前k个素数的指数均为偶数
第三步:在第二步中找到线性相关的行之后另a为相应xj的乘积,b为yj的乘积开平方,然后求a+b与n的最大公因子
ch5 Monte Carlo算法
MC算法偶然会犯错,但它对于任何实例都能以高概率找到正确的解
MC算法是p-正确的:以不小于p的概率返回正确的解(1/2<p<1),算法优势为p-1/2
若MC算法对同一实例绝不给出两个不同的正确解,则为相容的或者一致的
可以通过多次调用同一个算法,选择次数出现最多的解
eg
MC(x)为一个一致的,0.75-正确的算法
MC3(x){
t=MC(x);
u=MC(x);
v=MC(x);
if t=u or t=v then return t;
else return v;
}//该算法为0.84-正确
偏真算法:MC(x)返回true时答案总是正确的,当返回false的时候才有可能产生错误的解
5.1 主元素问题
数组T中等于x的元素大于n/2,则x称为T的主元素
maj(T){
i=uniform(1..n);
x=T[i];
k=0;
for j=1 to n do {
if(T[j]==x) then k=k+1;
}
return k>n;
}
如果算法返回true,一定为正确,算法是一个偏真的1/2正确的算法
//调整后为0.75正确的算法
maj2(T){
if maj(T)then
return Ture;//success one time
else
return maj(T);
}
//MC算法改进
majMC(T,e){
k=lg(1/e);
//e=2^-k;
for i=1 to k do{
if maj(T) then return true;
}
return false;
}
5.2判断一个整数是否为素数
//简单算法
prime(n){
d=uniform(2..根号n)
return (n mod d)!=0;
}
//偏假的测定
Fermat(n){
a=uniform(1..n-1);
if a^n-1 mod n==1 then
return true;
else return false;
}
//Fermat测试改进
Btest(a,n){//n为计数,2<=a<=n-2,返回真说明n为强伪素数或者素数
s=0;
t=n-1;//t is even
repeat {s++:t=t/2}
until t mod 2=1;
x=a^t mod n;
if x=1 or x=n-1 then return true;
for i=1 to s-1 do{
x=x^2 mod n;
if x=n-1 then return true;
}
return false;
}
5.3 矩阵乘法验证
判定AB=C? 转换为判定XAB=XC?(X为一个长度为n的二值01向量)
goodproduct(A,B,C,n){//偏假的1/2-正确算法
for i=1 to n do{
x[i]=uniform(0..1);
}
if (XA)B=XC then
return true;
}
//改进
RepeatGoodProduct(A,B,C,n,k){
for i=1 to k do{
if goodproduct(A,B,C,n)=false then return false;
}
return true;
}//偏假的1-2^-k 正确算法