zoukankan      html  css  js  c++  java
  • 算法作业相关总结

    第一次算法作业共十题,包括简单的定积分求值、不等式证明、算法原理分析、搜索有序表、八皇后拓展、素数判定,主要是概率算法的掌握。

    对某些问题确定性算法求解起来时间很长,而概率算法则能相对容易求得正确结果,如快速排序随机划分问题、八皇后求解问题、判断大整数是否伪素数问题。

    概率算法分为数字算法、Mente Carlo算法、Las Vegas算法、Sherwood算法,其中MC算法不管正确与否总是给出一个结果,LV算法不返回错误的答案但有时根本找不到答案,MC和LV算法找到正确结果的概率正比于算法执行时间。Sherwood算法总是给出正确的答案,通常可以消除好坏实例之间的差别,用于当算法解决问题的平均时间远小于最坏时间。

    作业1,2,3均为数字概率算法。作业5估计集合X的势的概率算法。作业7是sherwood算法搜索有序数组问题。作业9求n=12~20最优StepVegas值利用LV算法和确定性回溯算法相结合。作业10用MC算法求100~10000以内错误素数(即强伪素数)的比例。

    其中:

    作业5当n足够大(2^31)时,估计的n与实际n相差太大。尝试提高随机数的范围但错误率仍然很大,估计是算法本身不合理的问题。

    作业7有序表通过两个序列确定, 分别是val和ptr,如下所示:

          i      1     2     3     4     5     6      7

    val[i]      2     3    13    1     5     21    8

    ptr[i]      2     5     6     1     7     0      3

    rank       2     3     6     1     4     7      5

    head=4    有序表:1,2,3,5,8,13,21     

    采用shuffle()方法对val序列进行随机处理,保证最后通过ptr能按照从小到大顺序正确输出val序列的元素。

    具体以

    i    1 2 3 4 5

    val 1 2 3 4 5

    ptr 2 3 4 5 0

    为例,如果i=1和i=2的列交换,则

    i    1 2 3 4 5

    val 2 1 3 4 5

    ptr 3 1 4 5 0

    继续交换,如果i=2和i=3的列交换,则

    i    1 2 3 4 5

    val 2 3 1 4 5 

    ptr 2 4 1 5 0

    注意到这两种交换即为shuffle()随机处理过程中典型的两类列交换,分别是"序列两端任一端和序列中间元素交换"与"序列中间任两列元素交换"。以第一种交换为例,val交换的元素为第1和第2列,所以在ptr中找值为1和2的,并将值为2的重新赋值为1,值为1的重新赋值为2,如果没找到值为1或2的则不作处理。算法采用vector实现ptr,利用algorithm中的find()方法找出ptr中指定元素的下标位置并重新赋值,从而实现通过ptr即可按序输出val。find()元素也能找出val中第一个元素的位置,即为ptr中值为1的下标对应的val元素。

    算法A为O(n)的确定算法,B为O(sqrt(n))的确定算法,算法D为概率算法。shuffle()耗时很多,对于顺序序列,算法B的表现和A一样差。随机算法D表现时好时坏。算法C表现始终很好。对于随机序列,算法B和算法C表现都很好,速度很快。而算法A效果要差。随机算法D表现时好时坏,算法具体运行的时间差别并不是很明显。

    作业9根据搜索过的平均节点数确定最优的StepVegas,最终当n=8(八皇后)时结果比较合理,当n=12~20随着随机放置的马的数量增大,算法的成功率迅速降低为0,导致最后的结果很不合理。怀疑是由于当n增大时生成的随机数随机效果不好导致算法成功率迅速降低,没有被验证。

    作业10由于求素数的算法为3/4正确、偏假的MC算法,导致当迭代次数为2~4时选出强伪素数的概率为(1-3/4)^(2~4),比较低的概率导致在100~10000中产生错误素数的比例很小。当改为迭代一次时,概率为1-3/4=1/4此时在100~10000中产生错误素数的比例稍微有所增加,也验证了MC算法迭代次数越多求出正确结果概率越大的结论。

    其中作业5求集合大小的算法(求指正):

    1 SetCount (X) {
    2   k ← 0; S ← Ф;
    3   a ← uniform(X);
    4   do {
    5   k++;
    6   S ← S∪{a}; a ← uniform(X);
    7   } while (a not in S)
    8   return 2k2/π
    9 }

    其中作业7的shuffle()算法:

    vector<int> Shuffle(int *val, vector<int> ptr, int n)
    {
        srand(time(0));
        int i = 1, j = 1, k = 1, st = (int)sqrt(n*1.0);
        vector<int>::iterator ir,jr;
        for(; i < st; i++)
        {
            j = (rand()%(n-1) + 1);
            Swap(val, i, j);
            ptr = SwapVector(ptr, i, j);
            ir = find(ptr.begin(),ptr.end(),i);
            jr = find(ptr.begin(),ptr.end(),j);
            if(ir != ptr.end()){
                ir = ptr.erase(ir,ir+1);//清除ptr中为i的值
                ptr.insert(ir,j);//增加j
            }
            if(jr != ptr.end()){
                jr = ptr.erase(jr,jr+1);
                ptr.insert(jr,i);
            }
        }
        return ptr;
    }

     作业9截图:

    生成超出32767(2^15-1)的随机数方法:

    1.rand()*rand()

    2.rand()*1.0/RAND_MAX*n (n>32767)

    3.对有m位数字的n,用随机生成每一位上的数字乘以对应的10的k次幂(k为该数字所在的位数,以321为例,3对应的k为2),最后相加

    4.rand()<<16 + rand()

    5.参考头文件里面的rand()函数,重写该函数

    6.线性同余,x2 = ((x1 * 1103515245) + 12345) & 0x7fffffff,这个同余式可以[0, 2147483647]上随机。

    其中1,3可能导致生成的随机数不是很随机。在windows下,RAND_MAX的值为32767(0x7fff),在linux下,RAND_MAX的值则是最大的32位正整数:2147483647(2的31次方减1:0xffffffff,该数也是欧拉发现的一个梅森素数)。其中6,线性同余参见http://www.cnblogs.com/xkfz007/archive/2012/03/27/2420154.html

    对于5:

    参见:http://www.oschina.net/code/explore/cygwin-1.7.7-1/newlib/libc/stdlib/rand_r.c

    参见http://blog.csdn.net/ammana_babi/article/details/1437498

     1 #include <stdlib.h>
     2 
     3 /** Pseudo-random generator based on Minimal Standard by
     4    Lewis, Goodman, and Miller in 1969.
     5  
     6    I[j+1] = a*I[j] (mod m)
     7 
     8    where a = 16807
     9          m = 2147483647
    10 
    11    Using Schrage's algorithm, a*I[j] (mod m) can be rewritten as:
    12   
    13      a*(I[j] mod q) - r*{I[j]/q}      if >= 0
    14      a*(I[j] mod q) - r*{I[j]/q} + m  otherwise
    15 
    16    where: {} denotes integer division 
    17           q = {m/a} = 127773 
    18           r = m (mod a) = 2836
    19 
    20    note that the seed value of 0 cannot be used in the calculation as
    21    it results in 0 itself
    22 */
    23       
    24 int
    25 _DEFUN (rand_r, (seed), unsigned int *seed)
    26 {
    27         long k;
    28         long s = (long)(*seed);
    29         if (s == 0)
    30           s = 0x12345987;
    31         k = s / 127773;
    32         s = 16807 * (s - k * 127773) - 2836 * k;
    33         if (s < 0)
    34           s += 2147483647;
    35         (*seed) = (unsigned int)s;
    36         return (int)(s & RAND_MAX);
    37 }
     1 static long my_do_rand(unsigned long *value)
     2 {
     3    /*
     4       这个算法保证所产生的值不会超过(2^31 - 1)这里(2^31 - 1)就是 0x7FFFFFFF。
     5       而 0x7FFFFFFF等于127773 * (7^5) + 2836,7^5 = 16807。
     6       整个算法是通过:t = (7^5 * t) mod (2^31 - 1)
     7       这个公式来计算随机值,并且把这次得到的值,作为下次计算的随机种子值。
     8    */
     9    long quotient, remainder, t;
    10    quotient = *value / 127773L;
    11    remainder = *value % 127773L;
    12    t = 16807L * remainder - 2836L * quotient;
    13    if (t <= 0)
    14       t += 0x7FFFFFFFL;
    15    return ((*value = t) % ((unsigned long)RANDOM_MAX + 1));
    16 }

    两者最后return处理方式不同但效果相同。

    关于GSL(GNU Scientific Library)库的利用:

    http://gnailuy.com/2011/07/10/gsl%E7%A7%91%E5%AD%A6%E8%AE%A1%E7%AE%97%E5%BA%93%E3%80%81%E9%9A%8F%E6%9C%BA%E5%8F%98%E9%87%8F%E7%9A%84erlang%E5%88%86%E5%B8%83%E4%B8%8Eweibull%E5%88%86%E5%B8%83/

    http://www.cnblogs.com/suda/archive/2012/03/03/2378644.html

    http://blog.csdn.net/daiyuchao/article/details/2218039

  • 相关阅读:
    写给实习生的第一天
    写给实习生的第一天
    写给实习生的第一天
    老师不能把你怎样,但外面的世界可以!
    老师不能把你怎样,但外面的世界可以!
    adjA=(detA)A-1
    如果它仅对输入0才得到输出0
    isotropic trace
    detAB=detAdetB
    解释 纯量矩阵
  • 原文地址:https://www.cnblogs.com/francfu/p/3456367.html
Copyright © 2011-2022 走看看