0-1 背包问题的扩展

问题提出:
  给定 n种物品和一背包, 物品的重量是 wi, 体积为 bi, 价值为 vi, 背包的容量为 C, 容积为 D, 问应如何选择装入背包中的物品, 使得装入背包中物品的总价值最大? 在选择装入背包的物品时, 对每种物品 i 只有两种选择, 即装入背包或不装入背包。不能将物品 i 装入背包多次, 也不能只装入部分物品 i。

算法分析:

0-1背包问题的两种扩展形式及其解法.rar

代码实现:

ContractedBlock.gif ExpandedBlockStart.gif Code
  1ExpandedBlockStart.gifContractedBlock.gif/**//* 0-背包问题扩展
  2 * By Flouse@2008年12月9日 17时06分28秒
  3 */

  4using System;
  5using System.Collections.Generic;
  6using System.Text;
  7
  8namespace YourNameSpace // 修改为统一的命名空间
  9ExpandedBlockStart.gifContractedBlock.gif{
 10ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>装车类</summary>
 11    public class Loading
 12ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 13ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>货车载重量(t)</summary>
 14        private int capacity;
 15ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>货车体积容量(m3)</summary>
 16        private int cubage;
 17ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>最优(运费最高)装载清单</summary>
 18        private List<string> optimizedBills = new List<string>();
 19        public float totalPrice;
 20
 21ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>运单信息(装载相关)</summary>
 22        public struct TranBill
 23ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 24ExpandedSubBlockStart.gifContractedSubBlock.gif            /**//// <summary>托运单号</summary>
 25            public string tranID;
 26ExpandedSubBlockStart.gifContractedSubBlock.gif            /**//// <summary>拆单号</summary>
 27            public int tranSplitID;
 28ExpandedSubBlockStart.gifContractedSubBlock.gif            /**//// <summary>重量(t),实际运算里四舍五入化整</summary>
 29            public float billWeight;
 30ExpandedSubBlockStart.gifContractedSubBlock.gif            /**//// <summary>体积(m3),实际运算里四舍五入化整</summary>
 31            public float billVolumn;
 32ExpandedSubBlockStart.gifContractedSubBlock.gif            /**//// <summary>运费</summary>
 33            public float tranPrice;
 34        }
;
 35
 36ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>初始化货车信息</summary>
 37        /// <param name="capacity">货车载重量(t)</param>
 38        /// <param name="cubage">货车体积容量(m3)</param>

 39        Loading(int capacity, int cubage)
 40ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 41            this.capacity = capacity;
 42            this.cubage = cubage;
 43        }

 44        ~Loading()
 45ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 46            GC.Collect();
 47            //?? 释放内存
 48        }

 49ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>求解最优装车方案</summary>
 50        /// <param name="tbs">待运的托运单</param>
 51        /// <param name="mode">重量、体积转整模式
 52        ///     <value>0.0f~1.0f, 当 mode = 0.5f 时,即为四舍五入方式;当 mode = 0.0f 时, 即为最贪婪方式;当 mode = 1.0f 时,即为最保险方式</value>
 53        ///     <example>(int)(billWeight + mode), (int)(billVolumn + mode)</example>
 54        /// </param>
 55        /// <returns></returns>

 56        public List<string> doLoad(TranBill[] tbs, float mode)
 57ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 58            int count = tbs.Length;
 59            int[] w = new int[count + 1];
 60            int[] v = new int[count + 1];
 61            float[] p = new float[count + 1];
 62            float[, ,] m = new float[count + 1, capacity + 1, cubage + 1];
 63            for (int i = 1; i <= count; i++)
 64ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 65                w[i] = (int)(tbs[i - 1].billWeight + mode);
 66                v[i] = (int)(tbs[i - 1].billVolumn + mode);
 67                p[i] = tbs[i - 1].tranPrice;
 68            }

 69            Knapsack(p, w, v, count, m);
 70            Trackback(m, w, v, tbs);
 71            return optimizedBills;
 72        }

 73
 74        private void Trackback(float[, ,] m, int[] w, int[] v, TranBill[] tbs)
 75ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 76            int _capacity = capacity, _cubage = cubage, n = tbs.Length;
 77            optimizedBills.Clear();
 78            for (int i = 1; i < n; i++)
 79ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 80                if (m[i, _capacity, _cubage] - m[i + 1, _capacity, _cubage] > 0.000001f)
 81ExpandedSubBlockStart.gifContractedSubBlock.gif                {
 82                    optimizedBills.Add(tbs[i - 1].tranID + '.' + tbs[i-1].tranSplitID);
 83                    _capacity -= w[i];
 84                    _cubage -= v[i];
 85                }

 86            }

 87            if (m[n, _capacity, _cubage] > 0) optimizedBills.Add(tbs[n - 1].tranID + '.' + tbs[n - 1].tranSplitID);
 88        }

 89
 90ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>采用动态规划标记法(0-1背包问题算法)</summary>
 91        /// <param name="p"></param>
 92        /// <param name="w"></param>
 93        /// <param name="v"></param>
 94        /// <param name="n"></param>
 95        /// <param name="m"></param>

 96        private void Knapsack(float[] p, int[] w, int[] v, int n, float[, ,] m)
 97ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 98            int wMax = Math.Min(w[n] - 1, capacity);
 99            int vMax = Math.Min(v[n] - 1, cubage);
100
101            int i, j, k;
102
103            for (i = 0, j = 0; i <= wMax; i++)
104                for (j = 0; j < cubage; j++)
105                    m[n, i, j] = 0;
106            for (j = 0; j <= vMax; j++)
107                for (i = wMax+1; i < capacity; i++)
108                    m[n, i, j] = 0;
109
110            for (i = w[n]; i <= capacity; i++)
111                for (j = v[n]; j <= cubage; j++)
112                    m[n, i, j] = p[n];
113
114            for (k = n - 1; k > 1; k--)
115ExpandedSubBlockStart.gifContractedSubBlock.gif            {
116                wMax = Math.Min(w[k] - 1, capacity);
117                vMax = Math.Min(v[k] - 1, cubage);
118
119                for (i = 0, j = 0; i <= wMax; i++)
120                    for (j = 0; j < cubage; j++)
121                        m[k, i, j] = m[k + 1, i, j];
122                for (j = 0; j <= vMax; j++)
123                    for (i = wMax+1; i < capacity; i++)
124                        m[k, i, j] = m[k + 1, i, j];
125
126                for (i = w[k]; i <= capacity; i++)
127                    for (j = v[k]; j <= cubage; j++)
128                        m[k, i, j] = Math.Max(m[k + 1, i, j], m[k + 1, i - w[k], j - v[k]] + p[k]);
129            }

130            m[1, capacity, cubage] = m[2, capacity, cubage];
131            if (capacity >= w[1&& cubage >= v[1]) m[1, capacity, cubage] = Math.Max(m[1, capacity, cubage], m[2, capacity - w[1], cubage - v[1]] + p[1]);
132
133            totalPrice = m[1, capacity, cubage];
134        }

135
136        // 回溯法,示实现
137        //class BackBag{
138        //public:
139        //    BackBag(int W){
140        //        maxW = W;
141        //        ac = maxValue = nowValue = 0;
142        //    }
143        //    void KnapSack(int v[], int c[], bool used[], int n){    //回溯法
144        //        for (int i = 0; i < n; i++){
145        //            nowValue += v[i];
146        //            ac += c[i];
147        //            used[i] = true;
148        //        }
149        //        search(0, v, c, used, n);
150        //    }
151        //    void search(int i, int v[], int c[], bool used[], int n){
152        //        if (i==n) return;
153        //        if (nowValue <= maxValue) return;
154        //        if (ac <= maxW){
155        //            maxValue = nowValue;
156        //            return;
157        //        }        
158        //        nowValue -= v[i];    
159        //        ac -= c[i];
160        //        used[i] = false;
161        //        search(i+1, v, c, used, n);    //考虑不取i
162        //        nowValue += v[i];
163        //        ac += c[i];
164        //        used[i] = true;
165        //        search(i+1, v, c, used, n);    //考虑取i
166        //    }
167        //    int getMaxV(){
168        //        return maxValue;
169        //    }
170        //private:
171        //    int maxW;    //背包所能承受的重量
172        //    int ac;
173        //    int maxValue;
174        //    int nowValue;
175        //};
176
177ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>调用示例</summary>
178        /// <param name="args"></param>

179        static void Main(string[] args)
180ExpandedSubBlockStart.gifContractedSubBlock.gif        {
181            Loading l = new Loading(55);   // 设置货车的重容和体容
182
183            int n = Convert.ToInt32(Console.ReadLine());
184            TranBill[] tranBills = new TranBill[n];
185            string inStream;
186            for (int i = 0; i < n; i++)
187ExpandedSubBlockStart.gifContractedSubBlock.gif            {
188                inStream = Console.ReadLine();
189                string[] temp = inStream.Split('\t');
190                tranBills[i].tranID = temp[0];
191                tranBills[i].tranSplitID = int.Parse(temp[1]);
192                tranBills[i].billWeight = float.Parse(temp[2]);
193                tranBills[i].billVolumn = float.Parse(temp[3]);
194                tranBills[i].tranPrice = float.Parse(temp[4]);
195            }

196            List<string> optimizedBills = l.doLoad(tranBills, 0.5f);  // 执行最优装载求解
197            Console.WriteLine(l.totalPrice);                    // 最大托运费
198            foreach (string s in optimizedBills)                // 装载序列
199ExpandedSubBlockStart.gifContractedSubBlock.gif            {
200                Console.Write(s + '\t');
201            }

202        }

203    }

204}

205
206ExpandedBlockStart.gifContractedBlock.gif/**//* 示例输入
2075
208tran    1    1    1    100
209tran    2    1    1    100
210tran    3    1    1    100
211tran    4    1    1    100
212tran    5    1    1    100
213*/

转载于:https://www.cnblogs.com/Flouse/archive/2008/12/09/loading.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值