已知总金额和几个商品单价,查找每个商品各取几个可以最接近或等于总价,取最优解实现程序

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //10个试剂
            var materialList = new List<Material>();
            for (int i = 0; i < 5; i++)
            {
                var material = new Material()
                {
                    Code = i + 1,
                    Name = "Material" + (i + 1).ToString(),
                    Price = (i + 1),
                };
                materialList.Add(material);
                material.QtyList = new List<int>();
                int j = 1;
                //最多取20个
                while (j <= 5)
                {
                    material.QtyList.Add(j);
                    j++;
                }
            }

            Console.WriteLine($"MaterialList = {Newtonsoft.Json.JsonConvert.SerializeObject(materialList)}");
            decimal total = 0;
            int totalAmount = 70;
            bool flag = false;
            var diffList = new List<Diff>();
            plus(new Diff(), materialList, diffList, totalAmount, total, ref flag);
            var diff = diffList.OrderBy(p => p.DiffAmt).FirstOrDefault();
            Console.ReadLine();
        } 
        
        public static void plus(Diff diff, List<Material> materialList, List<Diff> diffList, decimal totalAmount, decimal total, ref bool flag)
        {
            if (flag)
                return;

            if (materialList != null && materialList.Any())
            {
                var material = materialList.First();
                var list = materialList.Where(p => p.Code != material.Code).ToList();
                foreach (var qty in material.QtyList)
                {
                    if (flag)
                        break;

                    if (totalAmount >= material.Price * qty + total)
                    {
                        var oldTotal = total;
                        oldTotal += material.Price * qty;
                        UpdateDiff(diff, material.Code, qty);
                        if (list.Any())
                            plus(diff, list, diffList, totalAmount, oldTotal, ref flag);
                        else
                        {
                            diff.DiffAmt = totalAmount - oldTotal;
                            diffList.Add(DeepCopy(diff));
                            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(diff));
                            if (diff.DiffAmt == 0)
                            {
                                flag = true;
                                break;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 深度拷贝对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T DeepCopy<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer xml = new XmlSerializer(typeof(T));
                xml.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                retval = xml.Deserialize(ms);
                ms.Close();
            }
            return (T)retval;
        }

        public static void UpdateDiff(Diff diff, int index, int qty)
        {
            var propName = "Number" + index.ToString();
            if (diff.GetType().GetProperty(propName) != null)
            {
                diff.GetType().GetProperty(propName).SetValue(diff, qty);
            }
        }

        public static void showLog(List<int> list)
        {
            string str = string.Join(",", list.ToArray());
            Console.WriteLine(str);
        }
    }

    public class Material
    {
        public int Code { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public int Qty { get; set; }
        public List<int> QtyList { get; set; }
    }

    public class Diff
    {
        public int Number1 { get; set; }
        public int Number2 { get; set; }
        public int Number3 { get; set; }
        public int Number4 { get; set; }
        public int Number5 { get; set; }
        public int Number6 { get; set; }
        public int Number7 { get; set; }
        public int Number8 { get; set; }
        public int Number9 { get; set; }
        public int Number10 { get; set; }
        public decimal DiffAmt { get; set; }
    }
}

  

posted on 2021-12-11 20:02  itjeff  阅读(162)  评论(0编辑  收藏  举报

导航