背包算法,C#

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

ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
InBlock.gif    
/// KnapSack 背包问题。
ExpandedBlockEnd.gif    
/// </summary>

None.gif      public   class  KnapSack
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 可放入背包的物件
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public interface PackItem
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// 可比对的值,统一转为decimal
ExpandedSubBlockEnd.gif            
/// </summary>

ExpandedSubBlockStart.gifContractedSubBlock.gif            decimal Value dot.gifget; }
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 用来做位屏蔽的数组
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private int[] mask = null;
InBlock.gif
InBlock.gif        
public KnapSack()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{            
ExpandedSubBlockEnd.gif        }

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

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

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

ExpandedSubBlockEnd.gif                }

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

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

ExpandedSubBlockEnd.gif            }

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

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 初始化 mask
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <param name="arrayLen"></param>

InBlock.gif        private void initMask(int arrayLen)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            mask 
= new int[arrayLen];
InBlock.gif            
for(int i=0;i < arrayLen;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                mask[i] 
= (1 << i);            //左移
ExpandedSubBlockEnd.gif
            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 取得组合总数,高中数学忘记了吧,复习吧
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="upper"></param>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

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

InBlock.gif            
return c;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 阶乘的递归算法
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="n"></param>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        private int GetSeq(int n)                    
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(n > 1)
InBlock.gif                
return n * GetSeq(n-1);
InBlock.gif            
return 1;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
测试#region 测试
InBlock.gif        
public class TestPackObject : BackPack.PackItem
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
int v;
InBlock.gif            
public TestPackObject(int v)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.v = v;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// 可比对的值,统一转为decimal
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            public decimal Value
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif                
get dot.gifreturn v; }
ExpandedSubBlockStart.gifContractedSubBlock.gif                
set dot.gif{ v = (int) value; }
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
public static void test()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            TestPackObject[] array 
= new TestPackObject[5];    // { 1,4,3,6,10 };
InBlock.gif
            array[0= new TestPackObject(1);
InBlock.gif            array[
1= new TestPackObject(4);
InBlock.gif            array[
2= new TestPackObject(3);
InBlock.gif            array[
3= new TestPackObject(6);
InBlock.gif            array[
4= new TestPackObject(10);
InBlock.gif            
InBlock.gif            KnapSack ks 
= new KnapSack();
InBlock.gif
InBlock.gif            
decimal sum = 0;
InBlock.gif            KnapSack.PackItem[] result 
= ks.EndList(array,12,ref sum);
InBlock.gif            Console.WriteLine(
"sum=" + sum);
InBlock.gif            
foreach(KnapSack.PackItem item in result)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(
"object.value=" + item.Value);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

这个算法最多不能超过32个物件。

转载于:https://www.cnblogs.com/xiaotaoliang/archive/2006/03/21/354758.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值