c#最优解算法Google Optimization Tools

  1. 背景
    1.   发票报销,比如一个月饭贴500元。手里一把发票,怎么凑个最优解?
  2. 废话
    1.  自己写个?算了吧,40了,算法都撂下了。17年的code职涯只是ctrlC ctlvV吗?惭愧。web开发让你就是个拧螺丝的。还是网上找找吧~
  3. 最优组合算法(多个结果) 
    1.   这个代码实现了,但是可能算法不够优雅。
    2.     /// <summary>
          /// 最优组合算法(多个结果)
          /// </summary>
          internal class TheMaxValue
          {
              public static void SortTest(double[] args, double argsum)//数组。和
              {
                  Array.Sort(args);//升序
                  Array.Reverse(args);//取反变倒叙
                  List<double> List2 = new List<double>(args);//整型数组转list
                  for (int i = 0; i < List2.Count; i++)
                  {
                      List<double> List3 = new List<double>();
                      List3.Add(List2[i]);
                      List2.RemoveAt(i);
                      for (int j = 0; j < List2.Count; j++)
                      {
                          if ((double)List2[j] <= argsum - CountList(List3) - 0.5)
                          {
                              List3.Add(List2[j]);
                              List2.RemoveAt(j);
                              j = -1;
                          }
                      }
                      string strArray = string.Join(",", List3); 
                      Console.WriteLine($"为每次分组的结果:{strArray}");
                      i = -1;
                  }
              }
              public static double CountList(List<double> list)
              {
                  double sum = 0;
                  for (int i = 0; i < list.Count(); i++)
                  {
                      sum += list[i];
                  }
                  return sum;
              }
               
      
              //返回结果可用结果集来接收: 
              public static Dictionary<int, List<double>> Sort(double[] args, double argsum)//数组。和
              {
                  Dictionary<int, List<double>> List = new Dictionary<int, List<double>>();
                  Array.Sort(args);//升序
                  Array.Reverse(args);//取反变倒叙
                  List<double> List2 = new List<double>(args);//整型数组转list
                  int count = 0;//List中元素键
                  for (int i = 0; i < List2.Count; i++)
                  {
                      List<double> List3 = new List<double>();
                      List3.Add(List2[i]);
                      List2.RemoveAt(i);
                      for (int j = 0; j < List2.Count; j++)
                      {
                          if ((double)List2[j] <= argsum - CountList(List3) )
                          {
                              List3.Add(List2[j]);
                              List2.RemoveAt(j);
                              j = -1;
                          }
                      }
                      List.Add(count++, List3);
                      i = -1;
                  }
                  return List;
              } 
                  
          }

       

    3. 直接调用,可以得到多个解。由于可能手里发票少凑不到,我调了附近的数
       internal class Program
          {
              static void Main(string[] args)
              { 
                  //调用方法: 
                  //int[] arr = { 1, 595, 600, 499, 497, 476, 5, 4, 3, 2, 1, 39, 500, 400, 455, 466, 478, 483, 35, 16, 5, 15, 6, 7, 8, 4, 7, 35, 13, 10, 2, 21, 40, 41, 33, 39, 31, 26, 11, 51, 77, 43, 36, 81, 23, 15, 72, 45, 83, 29, 55, 2, 3, 6, 9, 4, 5, 5, 6, 7, 4, 3 };
      
                  string[] temp = "1, 595, 600, 499, 497, 476, 5, 4, 3, 2, 1, 39, 500, 400, 455, 466, 478, 483, 35, 16, 5, 15, 6, 7, 8, 4, 7, 35, 13, 10, 2, 21, 40, 41, 33, 39, 31, 26, 11, 51, 77, 43, 36, 81, 23, 15, 72, 45, 83, 29, 55, 2, 3, 6, 9, 4, 5, 5, 6, 7, 4, 3".Split(',');
                  double[] ints = new double[temp.Length];//int类型数组 
                  for (int i = 0; i < temp.Length; i++)
                  {
                      ints[i] = Convert.ToInt32(temp[i]);//整数数组
                  }
                  int len = Convert.ToInt32(450);
                  int lenS = len - 10;
                  int lenM = len + 10;
                  while(lenS <= lenM){ 
                      GetMax(ints, lenS);
                      lenS++;
                  }
      
                  Console.Read();
              }
      
              private static void GetMax(double[] ints, double len)
              {
                  Console.WriteLine(len);
                  var sb = new StringBuilder();
                  Dictionary<int, List<double>> reslist = TheMaxValue.Sort(ints, len);
                  for (int i = 0; i < reslist.Count(); i++)
                  {
                      string str = $"miss:{len-reslist[i].Sum()} sum:{reslist[i].Sum()}——";
                      for (int j = 0; j < reslist[i].Count(); j++)
                      {
                          str += reslist[i][j] + ",";
                      }
                      sb.Append(str + "\r\n");
                  }
                  Console.WriteLine(sb.ToString());
                  Console.WriteLine();
              }
          }

       

    4.  

       

       

  4. Google Optimization Tools
    1. 又找到了权威的c++,应该快了。
    2. 看代码,很明显,这个问题就是 背包简化了。
    3. using System;
      using System.Collections.Generic;
      using Google.OrTools.Algorithms;
      
      namespace ConsoleApp1
      {
      
          /// <summary>
          /// 背包 ConsoleAppCoreOR-Tools
          /// https://developers.google.cn/optimization/pack/knapsack?hl=zh-cn#java_4
          /// </summary>
          public class Knapsack
          {
              public static void MainTest()
              {
                  KnapsackSolver solver = new KnapsackSolver(
                      KnapsackSolver.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample");
                  //包含项权重的矢量
                  //long[] values = { 360, 83, 59, 130, 431, 67,  230, 52,  93,  125, 670, 892, 600, 38,  48,  147, 78,
                  //              256, 63, 17, 120, 164, 432, 35,  92,  110, 22,  42,  50,  323, 514, 28,  87,  73,
                  //              78,  15, 26, 78,  210, 36,  85,  189, 274, 43,  33,  10,  19,  389, 276, 312 };
                  //包含项目值的向量
                  //long[,] weights = { { 7,  0,  30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0,  36, 3,  8,  15,
                  //                  42, 9,  0,  42, 47, 52, 32, 26, 48, 55, 6,  29, 84, 2,  4,  18, 56,
                  //                  7,  29, 93, 44, 71, 3,  86, 66, 31, 65, 0,  79, 20, 65, 52, 13 } };
                  long[] values = { 1, 595, 600, 499, 497, 476, 5, 4, 3, 2, 1, 39, 500, 400, 455, 466, 478, 483, 35, 16, 5, 15, 6, 7, 8, 4, 7, 35,
                      13, 10, 2, 21, 40, 41, 33, 39, 31, 26, 11, 51, 77, 43, 36, 81, 23, 15, 72, 45, 83, 29, 55, 2, 3, 6, 9, 4, 5, 5, 6, 7, 4, 3 }; 
      
                  long[,] weights = { { 1, 595, 600, 499, 497, 476, 5, 4, 3, 2, 1, 39, 500, 400, 455, 466, 478, 483, 35, 16, 5, 15, 6, 7, 8, 4, 7, 35,
                      13, 10, 2, 21, 40, 41, 33, 39, 31, 26, 11, 51, 77, 43, 36, 81, 23, 15, 72, 45, 83, 29, 55, 2, 3, 6, 9, 4, 5, 5, 6, 7, 4, 3 } };
                  long[] capacities = { 650 };
      
                  solver.Init(values, weights, capacities);
                  long computedValue = solver.Solve();
      
                  Console.WriteLine("Optimal Value = " + computedValue);
                  int len = values.Length;
                  var  packed_items = new List<int>() ;
                  var packed_weights = new List<long>() ;
                  long total_weight = 0;
                  for (int i = 0; i < len; i++)
                  {
                      if (solver.BestSolutionContains(i))
                      {
                          packed_items.Add (  i);
                          packed_weights.Add(weights[0, i]); 
                          total_weight += weights[0, i];
                      }
                  }
                  Console.WriteLine($"'Total weight:', {total_weight}");
                  Console.WriteLine($"'Packed items:', {string.Join(',', packed_items)}");
                  Console.WriteLine($"'Packed_weights:', {string.Join(',',packed_weights)}");  
      
              }
          }
      }
      

        

 

 

posted @ 2023-01-29 16:57  elegydance  阅读(93)  评论(0编辑  收藏  举报