zoukankan      html  css  js  c++  java
  • 背包算法,C#

    穷举法,这个最好理解了,省得死那么多脑细胞

    /// <summary>
        
    /// KnapSack 背包问题。
        
    /// </summary>

        public class KnapSack
        
    {
            
    /// <summary>
            
    /// 可放入背包的物件
            
    /// </summary>

            public interface PackItem
            
    {
                
    /// <summary>
                
    /// 可比对的值,统一转为decimal
                
    /// </summary>

                decimal Value get; }
            }

            
    /// <summary>
            
    /// 用来做位屏蔽的数组
            
    /// </summary>

            private int[] mask = null;

            
    public KnapSack()
            
    {            
            }

            
    /// <summary>
            
    /// 穷举
            
    /// </summary>
            
    /// <param name="array">PackItem对象数组</param>
            
    /// <param name="upperLimit">比对上限</param>
            
    /// <param name="resultSum">最后的总和结果</param>
            
    /// <returns>被挑选对象的数组</returns>

            public PackItem[] EndList(PackItem[] array,decimal upperLimit,ref decimal resultSum)
            
    {            
                initMask(array.Length);                        
    //初始化屏蔽数组

                
    int spaceNum = GetSpaceNum(array.Length);    //穷举数
                
                
    int plan = 0;                        //选择的方案号
                decimal max = 0;                    //能达到的最大值
                decimal sum = 0;                    //阶段性统计数
                for(int i=1;i <= spaceNum;i++)        //穷举第 i 种情况
                {
                    sum 
    = 0;                                //开始一种新情况,阶段性统计数归零
                    for(int j=0; j < array.Length; j++)        //处理每个物件
                    {                    
                        
    if((i & mask[j]) == mask[j])        //在本方案(i)中,第 j 个物件是否要选择
                        {
                            sum 
    += array[j].Value;            //选择第j个物件,价值加到阶段性统计数上            
                        }

                    }

                    
    if( sum > max && sum <= upperLimit)        //是否满足条件?
                    {
                        max 
    = sum;                            //满足条件,设定最新的最大值
                        plan = i;                            //记录下来这是第几个方案
                    }
                    
                }

                resultSum 
    = max;                            //结果
                IList result = new ArrayList();                //把选中的方案的物件挑出来
                for(int i=0;i < array.Length;i++)
                
    {
                    
    if((plan & mask[i]) == mask[i])            //第i个物件是否选中了。
                    {
                        result.Add(array[i]);                
    //选中了,加入到结果列表
                    }

                }

                PackItem[] resultArray 
    = new PackItem[result.Count];    //放到数组里面
                result.CopyTo(resultArray,0);
                
    return resultArray;                            //返回
            }

            
    /// <summary>
            
    /// 初始化 mask
            
    /// </summary>
            
    /// <param name="arrayLen"></param>

            private void initMask(int arrayLen)
            
    {
                mask 
    = new int[arrayLen];
                
    for(int i=0;i < arrayLen;i++)
                
    {
                    mask[i] 
    = (1 << i);            //左移
                }

            }

            
    /// <summary>
            
    /// 取得组合总数,高中数学忘记了吧,复习吧
            
    /// </summary>
            
    /// <param name="upper"></param>
            
    /// <returns></returns>

            private int GetSpaceNum(int upper)
            
    {
                
    int nUpper = GetSeq(upper);                //n!
                int c = 0;
                
    for(int i=1; i <= upper; i++)            //C(n,r) + C(n,r-1) +  + C(n,1)
                {                
                    
    int rs = GetSeq(i);                
                    
    int n2 = GetSeq(upper - i);
                    if(n2 == 0) 
                        c++;
                   else
                       c 
    += nUpper / (rs * n2);            //C(n,r) = n! / ( (n-i)! * i! )
                }

                
    return c;
            }

            
    /// <summary>
            
    /// 阶乘的递归算法
            
    /// </summary>
            
    /// <param name="n"></param>
            
    /// <returns></returns>

            private int GetSeq(int n)                    
            
    {
                
    if(n > 1)
                    
    return n * GetSeq(n-1);
                
    return 1;
            }


            
    测试

    这个算法最多不能超过32个物件。
  • 相关阅读:
    Windows API 第六篇 GetLocalTime
    _itoa _itow _itot atoi atof atol
    Window API 第五篇 WTSEnumerateProcesses
    获取计算机以及本机信息API
    Windows API 第四篇 文件操作
    [软工顶级理解组] 团队介绍和采访!
    2019 SDN上机第1次作业
    第01组 团队项目-需求分析报告
    团队项目-选题报告
    第二次结对编程作业
  • 原文地址:https://www.cnblogs.com/xiaotaoliang/p/354758.html
Copyright © 2011-2022 走看看