梁某人

发展才是硬道理

导航

背包算法,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个物件。

posted on 2006-03-21 12:17  涛仔28  阅读(2448)  评论(0编辑  收藏  举报