基于C#WinForm的0-1背包问题

问题描述:
0-1背包问题:给定n种物品和一背包。物品 i 的重量似乎 w[i],其价值为 v[i],背包的容量为 c。"0-1"的意思就是,对于每一件物品必须选择取(用1表示)或者不取(用0表示),且每件物品只能被取一次。问如何选择物品,使得装入背包中物品的总价值最大?
这是数学问题中的线性规划问题,我们可以在线性约束范围内求解目标表达式。

具体算法可以参考:https://www.jianshu.com/p/a66d5ce49df5。

编程准备:
在这里插入图片描述在窗体中添加相应控件。
首先看一下运行结果:
在这里插入图片描述左侧listbox中的是所有的物品,编号,重量(weight),价格(Price)。我采用的是将其ini文件中,在读取出来,后期也方便修改,可以在程序里面修改,也能直接修改本地文件。
右侧的richTextBox中的是0-1背包问题的二维递归表,第一行从左往右是背包容量依次增加,第一列为物品编号,其余为背包在对应容量下的最大价值。
主要代码:
这里我自己定义的一个类 myItems,里面有属性:物品编号,重量,价格(都为int型),选中状态(bool型)。
mmyAllItems 是所有物品组成的一个列表。
mmyBagMax 是背包最大容量。

        /// <summary>
        /// 所有商品存放list
        /// </summary>
        public static List<myItems> mmyAllItems = new List<myItems>();
        /// <summary>
        /// 背包最大容量
        /// </summary>
        public static int mmyBagMax = 10;  

主要算法实现

      int[,] mainRect = new int[mmyAllItems.Count, mmyBagMax + 1];

            for (int j = 1; j <= mmyBagMax; j++)
            {
    
    
                if (j >= mmyAllItems[0].weight)
                {
    
    
                    mainRect[0, j] = mmyAllItems[0].price;
                }
            }

            for (int i = 1; i < mmyAllItems.Count; i++)
            {
    
    
                for (int j = 1; j <= mmyBagMax; j++)
                {
    
    
                    //不装入背包
                    if (j < mmyAllItems[i].weight)
                    {
    
    
                        mainRect[i, j] = mainRect[i - 1, j]; 
                    }
                    else
                    {
    
    
                        //选择价值较大者
                        if (mainRect[i - 1, j - mmyAllItems[i].weight] + mmyAllItems[i].price > mainRect[i - 1, j])
                            mainRect[i, j] = mainRect[i - 1, j - mmyAllItems[i].weight] + mmyAllItems[i].price; 
                        else mainRect[i, j] = mainRect[i - 1, j];
                    }
                }
            }

            for (int i = mmyAllItems.Count - 1; i >= 1; i--)
            {
    
    
                if (mainRect[i, mmyBagMax] > mainRect[i - 1, mmyBagMax])
                {
    
    
                    mmyAllItems[i].IsChecked = true;
                    mmyBagMax -= mmyAllItems[i].weight; //物品i装入背包之前背包的容量            
                }
                else
                {
    
    
                    //没有装入背包
                    mmyAllItems[i].IsChecked = false;
                }
            }
            //第一个物品
            if(mmyBagMax!=0)
            {
    
    
                if (mainRect[0, mmyBagMax] != 0)
                    mmyAllItems[0].IsChecked = true;
                else
                    mmyAllItems[0].IsChecked = false;
            }
 最后再根据mmyAllItems中的每个item的IsChecked属性来判断有没有选中,再进行相应的窗体显示。在这里需要注意跨线程调用控件这个问题,可以采用委托。
 敬请各位指正。

猜你喜欢

转载自blog.csdn.net/Iawfy_/article/details/118491658