CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Java >  J2SE / 基础类

救命!最优订单问题

楼主jmlinlin(天堂射手)2005-04-02 09:16:11 在 Java / J2SE / 基础类 提问

问题是这样的  
  供货商提供n条供货单分别含数量范围和单价,如何从n个供货单中取单下单使得成本最低,例子如下  
  假设这里n=4,即有4条供货单(已经按单价排序)  
  ID         范围     单价  
  ------------------  
  0         1-10       1.95  
  1         11-20     1.90  
  2         11-20     1.98  
  3         1-10       3.0  
  -------------------  
   
  现在需要下31个货物的订单,应该如何从以上供货单中抽取使其成本最低,例如上面的例子我们可以取  
  id(1)     20个  
  id(2)     11个  
  成本为20*1.90+11*1.98=59.45最便宜  
  如何用程序实现?急啊,拜托各位~  
  问题点数:0、回复次数:31Top

1 楼milkbottle(奶瓶->好好学习,天天向上)回复于 2005-04-02 10:24:49 得分 0

简单写了一下,楼主可以参考,呵呵  
   
   
  import   java.util.*;  
   
  public   class   Test{  
   
                static   ArrayList   prices   =   new   ArrayList();  
     
                public   static   void   main(String   args[])  
                {  
                            int   quality   =   31;  
                              double   totalCost   =   0;  
   
                              prices.add(new   PriceUnit(0,1,10,1.95));  
              prices.add(new   PriceUnit(1,11,20,1.90));  
              prices.add(new   PriceUnit(2,11,20,1.98));  
              prices.add(new   PriceUnit(3,1,10,3.0));  
   
              while(quality!=0)  
                              {  
  PriceUnit   current   =   getMinPrice();    
  if(   quality   >   current.getMax())  
                                    {  
                                            quality   =   quality   -   current.getMax();  
            totalCost   +=   current.getMax()*current.getPrice();  
                                    }  
  else   if(quality   <   current.getMin())  
                                    {  
  continue;  
  }  
                                  else   if(quality   >=current.getMin()   &&   quality   <=   current.getMax())  
                                  {  
  totalCost+=   quality   *   current.getPrice();  
  quality   =   0;  
  }  
   
                              }  
   
    System.out.println(totalCost);  
                }  
   
   
                public   static   PriceUnit   getMinPrice()  
                {  
  double   min   =   ((PriceUnit)prices.get(0)).getPrice();  
                                  int   index   =   0;  
   
  for(int   i=0;i<prices.size();i++)  
                                  {  
                  PriceUnit   temp   =   (PriceUnit)prices.get(i);  
                                          if(temp.getPrice()<min   &&   temp.getStatus()==true)  
                                          {  
                                                  min   =   temp.getPrice();  
                                                  index   =   i;  
                                          }  
   
                                  }  
  ((PriceUnit)prices.get(index)).setStatus(false);  
  return   (PriceUnit)prices.get(index);  
                }  
   
  }  
   
  class   PriceUnit  
  {  
  private   int   id,   min,   max;  
                  private   double   price;  
                  private   boolean   available   =   true;  
   
                  public   PriceUnit(int   id,   int   min,   int   max,   double   price)  
                  {  
  this.id   =   id;  
                                  this.min   =   min;  
                                  this.max   =   max;  
                                  this.price   =   price;  
  }  
   
                  public   int   getId()  
                  {   return   id;}  
   
  public   int   getMin()  
                  {   return   min;}  
   
                  public   int   getMax()  
                  {   return   max;}  
   
                  public   double   getPrice()  
                  {   return   price;}  
   
                  public   boolean   getStatus()  
                  {   return   available;}  
   
                  public   void   setStatus(boolean   status)  
                  {   available   =   status;}  
                     
  }Top

2 楼jmlinlin(天堂射手)回复于 2005-04-02 18:32:55 得分 0

多谢!但算法有问题  
  若给出数据  
   
  0   1-10       6  
  1   11-20     6.1  
  2   12-21     10  
  3   9-12       10.5    
   
  quantity=11得出结果是60...Top

3 楼milkbottle(奶瓶->好好学习,天天向上)回复于 2005-04-02 19:04:45 得分 0

汗...   你给出的数据是无解的啊  
   
  当然算不对了....  
   
  Top

4 楼jmlinlin(天堂射手)回复于 2005-04-02 20:03:10 得分 0

呵呵,怎么会无解呢,恩,可能我的解释有问题~  
  当quantity=11的时候,若要选最低成本,只能到供应商ID(1)那去买11个,11个超过了供应商ID(0)的供应范围(它最多只能提供10个),所以,就以上数据来说,只能有两种办法,一是到ID(1)那去买,一个是到ID(3)那去买,相比之下还是ID(1)便宜...Top

5 楼007remember(绿原)回复于 2005-04-02 20:03:41 得分 0

ID         范围     单价  
  ------------------  
  0         1-10       1.95  
  1         11-20     1.90  
  2         11-20     1.98  
  3         1-10       3.0  
  4         1-10     1.90  
  5         11-20     2.90  
  -------------------  
  比如有个订单是30件货物  
  处理订单:  
  A:由一个供应商提供:  
            只有一种可能,10×3(由上述例子看出只有3个供应商(5个里有3个提供10件货物)做比较,找出最便宜的)  
  B:由二个供应商提供:  
            只有一种可能:10+20(总共有3×3=9种情况)  
  C:由三个供应商提供:  
          只有一种可能:10+10+10(总共有一种情况)  
  D:由四个供应商提供:  
          没有可能  
  E:由五个供应商提供:  
          没有可能  
            .  
            .  
            .  
            .  
   
  个人认为:  
          主要在于分解订单(分成几个供应商供货),确定由1-n(n>=2)个供应商是个关键。其中n是关键中的关键。  
        就题论题,比如上述例子。当订单是30件货物时,30÷10(所有供应商中提供最少货物的数量)=3  
  在这里就可以判断在大类上的情况。由1,2,3个供应商提供货物的3大类情况,即粗略判断出n=3。然后再分别计算3大类中的每个有多少种情况。  
   
  希望对楼主您有帮助  
  至于代码实现嘛,现在我感觉问题已经清楚啦  
  Top

6 楼milkbottle(奶瓶->好好学习,天天向上)回复于 2005-04-02 20:44:30 得分 0

哦哦,   是我理解错了,呵呵  
  再改改Top

7 楼jmlinlin(天堂射手)回复于 2005-04-02 20:47:38 得分 0

多谢帮忙~HOHOTop

8 楼simonxuluo(爱江山更爱美人)回复于 2005-04-02 21:07:01 得分 0

还是不明白题意,题目好像是一个供应商提供供货单,就我表面理解就是先找最便宜的开始吧Top

9 楼EdgarFrancis(Edgar)回复于 2005-04-02 21:42:03 得分 0

这其实不就是一个统筹学的基本的求整数解的问题,求最小和的问题,建议用方程列出然后或者用线性代数或者用统筹的东东得出算法,用java写出来就好了Top

10 楼simonxuluo(爱江山更爱美人)回复于 2005-04-02 21:52:06 得分 0

EdgarFrancis(Edgar),大虾,能写出统筹算法吗?谢谢Top

11 楼jmlinlin(天堂射手)回复于 2005-04-02 21:54:50 得分 0

问题是忘光了...你能给出个模型么Top

12 楼DanielYWoo(绿色毒汁)回复于 2005-04-02 22:07:27 得分 0

我懒得自己写了,看了楼上的,我就直接在这个基础上添了点代码,你看看能不能行  
  (没管代码风格,很乱,而且没做优化,效率很低,只是给你一个能跑的原型)  
  import   java.util.*;  
   
  public   class   Test   {  
          private   static   final   int   CANCEL_TRY_NEXT   =   -1;  
          static   ArrayList   prices   =   new   ArrayList();  
          static   Stack   opStack   =   new   Stack();  
          static   int   quantity   =   31;  
          static   double   totalCost   =   0;  
   
          public   static   void   main(String   args[])   {  
   
                  prices.add(new   PriceUnit(0,   1,   10,   1.95));  
                  prices.add(new   PriceUnit(1,   11,   20,   1.90));  
                  prices.add(new   PriceUnit(2,   11,   20,   1.98));  
                  prices.add(new   PriceUnit(3,   1,   10,   3.0));  
   
                  while   (quantity   !=   0)   {  
   
                          Operation   op   =   new   Operation();  
   
                          PriceUnit   current   =   getMinPrice();  
                          if   (current   ==   null)   {  
  //                                 if   (opStack.empty())   {  
  //                                         System.out.println("Not   found");  
  //                                         System.exit(0);  
  //                                 }  
                                  //push   back  
                                  op.id   =   CANCEL_TRY_NEXT;  
                                  opStack.push(op);  
                                  System.out.println("can   not   get   PriceUnit:   cancel");  
                          }   else   if   (quantity   >   current.getMax())   {  
                                  quantity   =   quantity   -   current.getMax();  
                                  totalCost   +=   current.getMax()   *   current.getPrice();  
   
                                  op.id   =   current.getId();  
                                  op.quantity   =   current.getMax();  
                                  op.price   =   current.getPrice();  
                                  opStack.push(op);  
                                  System.out.println("buy:   price:"   +   op.price   +   "   quantity:"   +   op.quantity);  
                          }   else   if   (quantity   <   current.getMin())   {  
                                  //push   back  
                                  current.setStatus(true);  
                                  op.id   =   CANCEL_TRY_NEXT;  
                                  opStack.push(op);  
                                  System.out.println("can   not   buy   enough   quantity:   cancel");  
                          }   else   if   (quantity   >=   current.getMin()   &&   quantity   <=   current.getMax())   {  
                                  totalCost   +=   quantity   *   current.getPrice();  
                                   
                                  op.id   =   current.getId();  
                                  op.quantity   =   quantity;  
                                  op.price   =   current.getPrice();  
                                  opStack.push(op);  
                                  quantity   =   0;  
                                  System.out.println("buy:   price:"   +   op.price   +   "   quantity:"   +   op.quantity);  
                          }  
   
                  }  
                  System.out.println("-------------------------------------------");  
                  System.out.println("totalCost="   +   totalCost);  
                  System.out.println("Operations:");  
                  while   (!opStack.empty())   {  
                          Operation   op   =   (Operation)   opStack.pop();  
                          System.out.println("buy   :   price:"   +   op.price   +   ",   quantity:"   +   op.quantity);  
                  }  
   
          }  
   
   
          private   static   boolean   isSkipped(PriceUnit   price,   Operation   lastOp)   {  
                  if   (lastOp   ==   null)   return   false;  
                  if   (price.getPrice()   >   lastOp.price)   return   false;  
                  return   true;  
          }  
          public   static   PriceUnit   getMinPrice()   {  
                  boolean   cancel   =   false;  
                  Operation   lastOp   =   null;  
                  if   (!opStack.empty())   {  
                          lastOp   =   (Operation)   opStack.peek();  
                          if   (lastOp.id   ==   CANCEL_TRY_NEXT)   {  
                                  opStack.pop();   //skip   the   flag  
                                  lastOp   =   (Operation)   opStack.pop();   //cancel   the   last   operation  
                                  for   (int   j   =   0;   j   <   prices.size();   j++)   {  
                                          PriceUnit   temp   =   (PriceUnit)   prices.get(j);  
                                          if   (temp.getId()   ==   lastOp.id)   {  
                                                  temp.setStatus(true);  
                                          }  
                                  }  
                                  cancel   =   true;  
                                  quantity   +=   lastOp.quantity;  
                                  totalCost   -=   lastOp.price   *   lastOp.quantity;  
                          }  
                  }  
   
   
                  //double   min   =   cancel   ?   lastOp.price   :   Double.MAX_VALUE;  
                  double   min   =   Double.MAX_VALUE;  
                  int   index   =   -1;  
   
                  for   (int   i   =   0;   i   <   prices.size();   i++)   {  
                          PriceUnit   temp   =   (PriceUnit)   prices.get(i);  
                          if   (temp.getPrice()   <=   min   &&   temp.getStatus()   ==   true   )   {  
                                  if   ((cancel   &&   !isSkipped(temp,   lastOp))   ||   !cancel)   {  
                                          min   =   temp.getPrice();  
                                          index   =   i;  
                                  }  
                          }  
   
                  }  
                  if   (index   ==   -1)   {  
                          return   null;  
                  }   else   {  
                          ((PriceUnit)   prices.get(index)).setStatus(false);  
                          return   (PriceUnit)   prices.get(index);  
                  }  
   
          }  
  }  
   
  class   Operation   {  
          public   int   id;  
          public   int   quantity;  
          public   double   price;  
  }  
   
  class   PriceUnit   {  
          private   int   id,   min,   max;  
          private   double   price;  
          private   boolean   available   =   true;  
   
          public   PriceUnit(int   id,   int   min,   int   max,   double   price)   {  
                  this.id   =   id;  
                  this.min   =   min;  
                  this.max   =   max;  
                  this.price   =   price;  
          }  
   
          public   int   getId()   {return   id;  
          }  
   
          public   int   getMin()   {return   min;  
          }  
   
          public   int   getMax()   {return   max;  
          }  
   
          public   double   getPrice()   {return   price;  
          }  
   
          public   boolean   getStatus()   {return   available;  
          }  
   
          public   void   setStatus(boolean   status)   {available   =   status;  
          }  
  }  
   
   
  Top

13 楼DanielYWoo(绿色毒汁)回复于 2005-04-02 22:09:48 得分 0

我没怎么多想,我大致觉得应该是从最便宜的买,买到后面数量不足,那就倒回去,尝试贵一点的.....  
   
  一直下去,就应该可以了,没多想,可能有问题,楼主您多试试那个程序Top

14 楼simonxuluo(爱江山更爱美人)回复于 2005-04-02 22:38:16 得分 0

测试过了,对某些数值不对,比如1~10之间,抛出java.util.EmptyStackException异常,可能是小bug,好难理解这个程序阿,栈的操作我已经忘了差不多了:)Top

15 楼jmlinlin(天堂射手)回复于 2005-04-02 22:48:59 得分 0

确实还是问题...  
  就我给的例子没问题,但如果换一下(ID0和ID1的单价对调)  
  ID         范围     单价  
  ------------------  
  0         1-10       1.90  
  1         11-20     1.95  
  2         11-20     1.98  
  3         1-10       3.0  
  -------------------  
  最便宜应该是   20*1.95+1.98*11=60.78  
  而您的程序结果是1.95*11+3*10+1.9*10=70.45  
   
  ...Top

16 楼simonxuluo(爱江山更爱美人)回复于 2005-04-02 23:12:01 得分 0

这个题是否请人工智能大师来讨论一下?Top

17 楼007remember(绿原)回复于 2005-04-02 23:35:37 得分 0

学习ingTop

18 楼jmlinlin(天堂射手)回复于 2005-04-03 01:06:32 得分 0

没人有想法了么,呵呵自己顶一下  
  Top

19 楼jmlinlin(天堂射手)回复于 2005-04-03 16:45:30 得分 0

没人了...Top

20 楼Mlfeng(枫叶染红)回复于 2005-04-03 17:23:36 得分 0

我不是JAVA   ,但我觉得问题应该是:  
  每次先价格进行从低到高排序,再对他们进行从你到高的顺序去求定单数。  
  ID         范围     单价  
  ------------------  
  0         1-10       1.90  
  1         11-20     1.95  
  2         11-20     1.98  
  3         1-10       3.0  
  -------------------  
  比如要30。那就可以先得到1.9最低,取出最大数10  
  还差的就到第二位价上取,得到的是20的1.95  
  那么最低价应该是:1.9*10+1.95+20=58  
  如果取的是10的就应该是:1.9*10=19  
  如果是40的那就是:1.9*10+1.95*20+1.98*10=77.8  
   
  不知对不对?Top

21 楼jmlinlin(天堂射手)回复于 2005-04-03 18:34:16 得分 0

这是最简单的办法,也是麻烦最多的事情,比如你考虑11个的话,这个方法就不是最优的了  
  10*1.90+1*3.0>11*1.95    
   
  Top

22 楼Mlfeng(枫叶染红)回复于 2005-04-03 19:47:35 得分 0

11应该就是     1.90*10+1.95*1当然小于11*1.95  
  是按价格排序,不是数量Top

23 楼jmlinlin(天堂射手)回复于 2005-04-03 20:53:39 得分 0

恩,你可能误会题意了,请仔细看一下,11表示ID1只提供11-20个,他不提供1-10个的,请仔细看Top

24 楼jmlinlin(天堂射手)回复于 2005-04-03 20:57:32 得分 0

再解释一下,订单需要11个货物,供应商人提供的供或单为  
  ID         范围     单价  
  ------------------  
  0         1-10       1.90  
  1         11-20     1.95  
  2         11-20     1.98  
  3         1-10       3.0  
  -------------------  
  已经按价格排序,范围表示供货商只提供该范围内数量的货物Top

25 楼winstarr(星仁)回复于 2005-04-03 21:16:55 得分 0

upTop

26 楼freshbig(智猪)回复于 2005-04-03 21:29:23 得分 0

这是一个背包问题  
  Top

27 楼qiongtumlL(海上孤魂)回复于 2005-04-03 21:46:52 得分 0

这个东西应该考虑模拟退火算法Top

28 楼DanielYWoo(绿色毒汁)回复于 2005-04-04 11:54:27 得分 0

呵呵,我改写的那个是贪婪法吧,那个应该是不能得最优解的,只是近似解。可能应该用动态规划,帮你顶一下Top

29 楼007remember(绿原)回复于 2005-04-04 12:41:06 得分 0

学习ing  
  帮您顶Top

30 楼vssivl(克斯)回复于 2005-04-04 16:14:28 得分 0

楼主题目给的不完全,如果给定31个,那应该从0到31的标价都给出来,比如  
   
  ------------------  
  0         1-10       1.95  
            11-40     1.80  
   
  1         11-20     1.90  
            21-40     1.81  
   
  2         11-20     1.98  
            21-40     1.82  
   
  3         1-10       3.0  
            11-25     2.8  
            26-40     2.7  
  -------------------  
   
  楼主给的条件实际上适用于给定总价格求可买的最多个数。  
  Top

31 楼jmlinlin(天堂射手)回复于 2005-04-06 10:49:39 得分 0

恩,差不多是这个意思,也可以说给定数量挑最优组合,唉,东西已经交出去了,参考了贪婪和背包的问题,看了有点晕了...Top

相关问题

  • 订单
  • 最优化 - 用料问题
  • 征集最优方法!
  • 求一最优算法
  • 最优下料算法
  • 求一最优算法
  • 求一最优sql,速度
  • 最优逼近算法紧急求助!!!
  • 一个最优化的问题!
  • cg1120(代码最优化)来拿分吧

关键词

  • 排序
  • 代码
  • priceunit
  • opstack
  • lastop
  • 最优
  • 供货
  • 订单
  • 货物
  • getminprice

得分解答快速导航

  • 帖主:jmlinlin

相关链接

  • CSDN Java频道
  • Java类图书
  • Java类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo