拉斯维加斯算法(转 用来说明算法导论题目!!!)

Monte Carlo algorithm will return an answer that is not necessarily
correct within a reasonable amount of time.
Las Vegas algorithm may take infinite time to compute an answer, but
the answer is guaranteed to be correct.

随机化算法(4) — 拉斯维加斯(Las Vegas)算法

已出连载

1.《随机化算法(1) — 随机数》

2.《随机化算法(2) — 数值概率算法》

3.《随机化算法(3) — 舍伍德(Sherwood)算法》

正文:

悟性不够,这一章看代码看了快一个上午,才理解。

上一章讲过《概率算法(3) — 舍伍德(Sherwood)算法》,但是他的有点是计算时间复杂性对所有实例而言相对均匀,而其平均时间复杂性没有改变。而拉斯维加斯算法怎么显著改进了算法的有效性。

拉斯维加斯算法的一个显著特征是它所作的随机性决策有可能导致算法找不到所需的解。因此通常用一个bool型函数表示拉斯维加斯算法。

void Obstinate(InputType x, OutputType &y)
{
 
    // 反复调用拉斯维加斯算法LV(x, y),直到找到问题的一个解
    bool success= false;
    while (!success) 
         success = LV(x,y);
}

考虑用拉斯维加斯算法解决N皇后问题

对于n后问题的任何一个解而言,每一个皇后在棋盘上的位置无任何规律,不具有系统性,而更象是随机放置的。由此容易想到下面的拉斯维加斯算法。
在棋盘上相继的各行中随机地放置皇后,并注意使新放置的皇后与已放置的皇后互不攻击,直至n个皇后已相容地放置好,或已没有下一个皇后的可放置位置时为止。注意这里解决的是找到其中一个方法,求不是求出N皇后的全部解。

这里提前说明一下,否则不好理解。

接下来的这个用Las Vegas算法解决N皇后问题,我们采用的是随机放置位置策略回溯法相结合,具体就是比如八皇后中,前几行选择用随机法放置皇后,剩下的选择用回溯法解决。

这个程序不是很好理解,有的地方我特别说明了是理解程序的关键,大家看时一定要认真了,另外,王晓东的书上先是用单纯的随机法解决,大家可以先去理解书上这个例子。然后再来分析我这个程序。不过那本书上关于这一块错误比较多,大家看时要注意哪些地方他写错了。

拉斯维加斯算法解决N皇后代码:

依然用到了RandomNumber.h头文件,大家可以去看下第一章,我就不贴出来了。

剩下部分的代码:

注意QueensLV()函数是这个程序的精髓所在。

Queen.h头文件

#ifndef QUEEN_H
#define QUEEN_H
 
class Queen
{
    friend bool nQueen(int);
private:
    bool Place(int k);             // 测试皇后k置于第x[k]列的合法性
    bool Backtrack(int t);         // 解n后问题的回溯法
    bool QueensLV(int stopVegas);  // 随机放置n个皇后拉斯维加斯算法
    int n, *x, *y;
};
 
#endif

Queen.cpp文件

#include <iostream>

#include "Queen.h"
#include "RandomNumber.h"
using namespace std;
 
bool Queen::Place(int k)
{
    // 测试皇后k置于第x[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;
}
 
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;
}
 
/*
* QueensLV是整个Las Vegas解n皇后的精髓。而且这个函数不好理解,我在这里具体分析下。
* k是第k行,x[k]表示第k行的皇后放在x[k]列
* 下面这两点解析请认真看了,我个人就是卡在这里半天了,但是理解后很简单。
* 标号①处:这里是遍历第k行所有可以放置的列号,用y保存下来,并用count记录有多少个位置可以放置
* 标号②处:这里利用上面保存的可以放置的列,然后随机取其中一列来放置第k行的皇后。这就是Las Vegas的精髓!
*/
// Author: Tanky Woo
// Blog:    www.WuTianQi.com
bool Queen::QueensLV(int stopVegas)
{
    // 随机放置n个皇后的拉斯维加斯算法
    RandomNumber rnd;    // 随机数产生器
    int k = 1;           // 下一个放置的皇后编号
    int count = 1;
    // 1 <= stopVegas <= n 表示允许随机放置的皇后数
    while((k <= stopVegas) && (count > 0))
    {
        count = 0;
        for(int i = 1; i<=n; ++i)      // ----------- ①
        {
            x[k] = i;
            if(Place(k))
                y[count++] = i;
        }
        if(count > 0)                   // -------------②
            x[k++] = y[rnd.Random(count)];   // 随机位置
    }
    return (count > 0);   // count > 0表示放置位置成功
}

Main.cpp主文件:

/*
* Author: Tanky woo
* Blog:   www.WuTianQi.com
* Date:   2010.12.9
* 拉斯维加斯(Las Vegas)算法解决N皇后问题
* 代码来至王晓东《计算机算法设计与分析》
*/
#include "Queen.h"
#include "RandomNumber.h"
#include <iostream>
using namespace std;
 
bool nQueen(int n)
{
    // 与回溯法结合的解n后问题的拉斯维加斯算法
    Queen X;
    // 初始化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 = q;
    X.x = p;
    // 设置随机放置皇后的个数
    int stop = 8;
    if(n > 15)
        stop = n-15;
    bool found = false;
    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;
}
 
int main()
{
    nQueen(8);
}

在8皇后问题中:

1.stopVegas=0表示完全使用回溯法解决问题。因此一定可以得到一组解。

2.stopVegas=8表示完全实用随机法解决问题。因此一定可以得到一组解。

注意书上说解决8皇后问题时,列出了一个不同stopVegas值时,所对应的算法成功率,在stopVegas=8时,他写着是0.1293,我个人认为是错的。接下来我说下自己这么理解的原因:

首先,这个程序为何会造成有失败的情况,那就是因为在随机求出前stopVegas行成立时,不代表后面N-stopVegas行用回溯就可以成立,因为这不是一个彻底的回溯。它是从stopVegas+1行开始计算,回溯不成立最后返回时,也只停留在stopVegas。

而我们在完全随机时,那么它就是反复调用随机位置放置n个皇后的Las Vegas算法,直至放置成功。所以当stopVegas=8时,他的成功率也应该是100%。

另外在stopVegas=3时,成功率等于0.49,趋近于0.5,大家可以试试,基本上每运行两次会有一次回来结果。

如果上面我的理解有错,欢迎大家指出,我的博客(www.WuTianQi.com)。

下一篇我会写《随机化算法(5) — 蒙特卡罗(Monte Carlo)算法》。

Tanky Woo原创,欢迎转载,转载请附上链接,请不要私自删除文章内任何关于本博客的链接。

Tanky Woo 标签: 随机算法拉斯维加斯算法Las Vegas

时间: 2024-12-29 06:42:50

拉斯维加斯算法(转 用来说明算法导论题目!!!)的相关文章

舍伍德算法(转 用来说明算法导论题目!!!)

随机化算法(3) — 舍伍德(Sherwood)算法 已出连载: 1.<随机化算法(1) — 随机数> 2.<随机化算法(2) — 数值概率算法> 正文: 这一章怎么说呢,我个人感觉不好理解,在网上查了一些资料,没发现有具体对舍伍德算法的介绍. 迄今为止看的最全面的就是王晓东的<计算机算法设计与分析>里讲的了.在网上查的一些资料也基本全和这本书上讲的一样,至于是这本书先写的,还是其他位置先写的,我就不做评论了. (有时间我把那本书上讲舍伍德的一段给拍下来放到文章里) 书

数值概率算法(转 用来说明算法导论题目!!!)

随机化算法(2) — 数值概率算法 接着上一篇: 随机化算法(1) — 随机数 在这章开篇推荐下chinazhangjie总结的随机算法,因为咱两看的是同一本书,所以大家也可以去参考下他的,总结的很不错. http://www.cnblogs.com/chinazhangjie/archive/2010/11/11/1874924.html (顺便再PS一下,小杰也是我论坛的C/C++问题求助板块的版主,C/C++小牛) 这一章我就把书中的一个例子举出来了,感觉虽然很简单,但是很有意思. 用随机

从有限状态机的角度去理解Knuth-Morris-Pratt Algorithm(又叫KMP算法,”看毛片“算法)

转载请加上:http://www.cnblogs.com/courtier/p/4273193.html 在开始讲这个文章前的唠叨话: 1:首先,在阅读此篇文章之前,你至少要了解过,什么是有限状态机,什么是KMP算法,因为,本文是从KMP的源头,有限状态 机来讲起的,因为,KMP就是DFA(Deterministic Finite Automaton)上简化的. 2:很多KMP的文章(有限自动机去解释的很少),写得在我看来不够好,你如果,没有良好的数学基础就很难去理解他们(比如下图), 因为,你

算法——字符串匹配之KMP算法

前言 本节介绍Knuth-Morris-Pratt字符串匹配算法(简称KMP算法).该算法最主要是构造出模式串pat的前缀和后缀的最大相同字符串长度数组next,和前面介绍的<朴素字符串匹配算法>不同,朴素算法是当遇到不匹配字符时,向后移动一位继续匹配,而KMP算法是当遇到不匹配字符时,不是简单的向后移一位字符,而是根据前面已匹配的字符数和模式串前缀和后缀的最大相同字符串长度数组next的元素来确定向后移动的位数,所以KMP算法的时间复杂度比朴素算法的要少,并且是线性时间复杂度,即预处理时间复

算法学习 并查集(笔试题目:找同伙)

题目背景太长,记得不清楚,暂参考<啊哈算法>一书,根据笔试题目大意改编如下: 警察正要捉获某地区的犯罪团伙,由于强盗人数过大,想查清楚有几个团伙非常困难. 根据上级指示,需要首先尽快抓获强盗A所在的团伙,这需要掌握 1 所在团伙的人数.先有资料如下: 强盗1 和 强盗2 是同伙 强盗3 和 强盗4 是同伙 强盗2 和 强盗5 是同伙 强盗3 和 强盗2 是同伙 注意,强盗的同伙的同伙也是同伙,问  强盗1 的同伙(不包括1自己)有多少人? 该题形式化表示如下: 每个测试实例首先包括2个整数:N

基本算法研究1-冒泡排序算法测试

基本算法研究1-冒泡排序算法测试 1.经典冒泡排序法基本原理 先看一个动态图,感觉比较形象: 冒泡排序(Bubble Sort)是一种简单的排序算法.默认是从小到大排序,即把最大的数据排在最后,相当于每次把最大数据像气泡一样浮到水面一样.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换. 基本步骤: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个.        2.对每一对相邻元素作同样的工作,从开始第一对

【机器学习算法-python实现】采样算法的简单实现

1.背景 采样算法是机器学习中比较常用,也比较容易实现的(出去分层采样).常用的采样算法有以下几种(来自百度知道): 一.单纯随机抽样(simple random sampling) 将调查总体全部观察单位编号,再用抽签法或随机数字表随机抽取部分观察单位组成样本. 优点:操作简单,均数.率及相应的标准误计算简单. 缺点:总体较大时,难以一一编号. 二.系统抽样(systematic sampling) 又称机械抽样.等距抽样,即先将总体的观察单位按某一顺序号分成n个部分,再从第一部分随机抽取第k

【JavaScript】【算法】JavaScript版排序算法

JavaScript版排序算法:冒泡排序.快速排序.插入排序.希尔排序(小数据时,希尔排序会比快排快哦) 1 //排序算法 2 window.onload = function(){ 3 var array = [0,1,2,44,4, 4 324,5,65,6,6, 5 34,4,5,6,2, 6 43,5,6,62,43, 7 5,1,4,51,56, 8 76,7,7,2,1, 9 45,4,6,7,8]; 10 //var array = [4,2,5,1,0,3]; 11 array

图灵算法群《啊哈算法》领读

--图灵算法群阅读计划(第一期) 领读人:Zoctopus·Lian 本书特色 一本充满智慧和趣味的算法入门书.没有枯燥的描述,没有难懂的公式,一切以实际应用为出发点. 书中涉及到的数据结构有栈.队列.链表.树.并查集.堆和图等:涉及到的算法有排序.枚举.深度和广度优先搜索.图的遍历,当然还有图论中不可以缺少的四种最短路径算法.两种最小生成树算法.割点与割边算法.二分图的最大匹配算法等. 书中通过幽默的语言配以可爱的插图来讲解算法,使用C语言实现. 适合读者 适合算法零基础入门和喜爱编程的朋友(