zoukankan      html  css  js  c++  java
  • Lua版组合算法

    高效率的排列组合算法--《编程珠矶》--Lua实现

    原文链接

    原文是python实现的,这里给出lua版本的实现

    组合算法   
      本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标  
      代表的数被选中,为0则没选中。     
      首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。     
      然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为   
      “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。     
      当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得   
      到了最后一个组合。     
      例如求5中选3的组合:     
      1   1   1   0   0   //1,2,3     
      1   1   0   1   0   //1,2,4     
      1   0   1   1   0   //1,3,4     
      0   1   1   1   0   //2,3,4     
      1   1   0   0   1   //1,2,5     
      1   0   1   0   1   //1,3,5     
      0   1   1   0   1   //2,3,5     
      1   0   0   1   1   //1,4,5     
      0   1   0   1   1   //2,4,5     
      0   0   1   1   1   //3,4,5  

    -- 从长度为m的数组中选n个元素的组合
    function comm.zuhe(atable, n)
        if n > #atable then
            return {}
        end
    
        local len = #atable
        local meta = {}
        -- init meta data
        for i=1, len do
            if i <= n then
                table.insert(meta, 1)
            else
                table.insert(meta, 0)
            end
        end
    
        local result = {}
    
        -- 记录一次组合
        local tmp = {}
        for i=1, len do
            if meta[i] == 1 then
                table.insert(tmp, atable[i])
            end
        end
        table.insert(result, tmp)
    
        while true do
            -- 前面连续的0
            local zero_count = 0
            for i=1, len-n do
                if meta[i] == 0 then
                    zero_count = zero_count + 1
                else
                    break
                end
            end
            -- 前m-n位都是0,说明处理结束
            if zero_count == len-n then
                break
            end
    
            local idx
            for j=1, len-1 do
                -- 10 交换为 01
                if meta[j]==1 and meta[j+1] == 0 then
                    meta[j], meta[j+1] = meta[j+1], meta[j]
                    idx = j
                    break
                end
            end
            -- 将idx左边所有的1移到最左边
            local k = idx-1
            local count = 0
            while count <= k do
                for i=k, 2, -1 do
                    if meta[i] == 1 then
                        meta[i], meta[i-1] = meta[i-1], meta[i]
                    end
                end
                count = count + 1
            end
    
            -- 记录一次组合
            local tmp = {}
            for i=1, len do
                if meta[i] == 1 then
                    table.insert(tmp, atable[i])
                end
            end
            table.insert(result, tmp)
        end
    
        return result
    end

    算法是经过优化的版本,效率还算可以,感兴趣的可以自己跑一下测试!

  • 相关阅读:
    「CF505E」 Mr. Kitayuta vs. Bamboos
    「CF1438D」 Powerful Ksenia
    Kruskal重构树
    20210528模拟赛总结
    20210527模拟赛总结
    20210526模拟赛总结
    20210525模拟赛总结
    CF #722 Div2题解
    洛谷P3652 csh和zzy的战争 题解
    [清华集训2012]模积和 题解
  • 原文地址:https://www.cnblogs.com/ksir16/p/8041457.html
Copyright © 2011-2022 走看看