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

需求通用算法

楼主tzlhr(泥土)2006-08-30 16:04:12 在 MS-SQL Server / 基础类 提问

需求通用算法:(要求顾客最大化原则)  
  商场搞活动送赠券:  
                        购商品A,现金100送10券一张,200送30券一张,张数不封顶  
                        购商品B,现金200送30券一张,   400送65券一张,张数不封顶  
                        购商品C,现金200送20券一张,500送60券一张,张数不封顶  
  产生的赠券通用  
  现顾客购买商品A 200元,商品B   450,商品C   1200,  
  支付方式:1000元赠卷,850元现金,问850现金应生成  
  各种券几张(券面金额相同算一种) 问题点数:50、回复次数:32Top

1 楼polestarxu(一点星光)回复于 2006-08-30 16:14:45 得分 0

upTop

2 楼j9988(j9988)回复于 2006-08-30 16:21:17 得分 0

1.先算出每100元奖的比例,比如:购商品B,400送65券一张   奖的比便最高.   首先考虑,其次是A   B的200送30   再次是C   500送60券一张  
  2.看看购买的数字是否达标.从高拿到低,这样得出:    
      购商品B   400送65券一张  
      购商品A   200送30券一张  
      购商品C,200送20券一张  
  Top

3 楼tzlhr(泥土)回复于 2006-08-30 16:30:30 得分 0

比例高是不错的,但是还要考虑现金的总额,  
              例:商品A   80   送   20     20/80=0.25  
                      商品B   70   送   15     15/70=0.21  
                      按比率,2张20的券,则40,但实际应生成3张15的券45例Top

4 楼ww3347(新来的)回复于 2006-08-30 16:32:43 得分 0

j9988算法是很容易想到的办法,但是不对,还要考虑现金全部分配出去的问题。  
   
  假设现金200送180,300送300,400送450。顾客花500元。  
  按你的算法,只能取400送450,剩余100现金浪费了。  
  实际取现金200送180,300送300,可得券480。此情况下是最优的。  
   
  只负责挑错:)  
  Top

5 楼j9988(j9988)回复于 2006-08-30 16:44:11 得分 0

有道理!没想到.  
   
          那只好穷举了.跟据顾客购买的每种商品,金额.在客户购买本商品现金额度范围内.循环穷举.找出最大的金额.Top

6 楼j9988(j9988)回复于 2006-08-30 17:05:29 得分 0

这得花点功夫,多一点实例.穷举加判断.  
   
  850元现金如何根据200   450   1200分配.就是A分配现金封顶200   B封顶450,C封顶850.  
   
  这样:    
  A分配现金封顶200   只有两种方案:现金100送10券一张X2,或   200送30券一张X1    
  B分配现金封顶450   现金200送30券一张X2   或   400送65券一张    
  C分配现金封顶850   现金200送20券一张X4   或   500送60券X1+200   送20券X1  
  根据以上ABC可能的方案穷举.得出最高金额.  
   
  Top

7 楼j9988(j9988)回复于 2006-08-30 17:08:47 得分 0

就是先算A   B   C最多可出那种几张奖券,然后这几种来穷举分配.得出最大金额的分配方案.Top

8 楼ww3347(新来的)回复于 2006-08-30 17:11:07 得分 0

继续:)怎么穷举?  
  注意:不是你列举的6个东西的组合。Top

9 楼j9988(j9988)回复于 2006-08-30 17:18:20 得分 0

就是先根据购买商品的金额,算出每种商品可能的分配的现金数,  
  比如你只购A200元.但现金是850元,它不可能在里面拿850元奖券吧.最多只能分它200元.  
  这样它有可能出现的是100元可最多出2张   200元可最多出1张.  
  依此类堆算出B   C   最多出的券别张数  
   
  比以上结果的限制范围内来穷举.Top

10 楼toto1980(^涛^)回复于 2006-08-30 17:19:35 得分 0

1.付款金额最大可能分配出去,计算可得奖券  
  2.j9988(j9988)的方法计算可得奖券  
  两者取最大Top

11 楼j9988(j9988)回复于 2006-08-30 17:21:43 得分 0

穷举的可能性有:  
  1.   A   100X2   +B   200X2   +C   200X2  
  2.   A   100X1   +B   200X2   +C   500X1  
  3.   A   200X1   +B   200X2   +C   200X1  
  ...........  
  同时各算出以上的奖券金额.取奖券金额最大的一组.Top

12 楼specialsoldier(雪地撒野~噢姐姐,我要回家)回复于 2006-08-30 17:29:19 得分 0

j9988算法有问题:  
  1,上面说了要考虑现金全部分配的问题.可能给了比例高的,回余一些现金.但给比例低的,现金用的多.这样现金的利用率也算有个影响因素.  
  2.还要考虑的是,这个所谓的比例是不定的,可能买100送10,买200就送180,这样的分段比例需要更多的判断来支持.  
   
  穷举肯定可以,但是有其他方法的.  
   
  Top

13 楼ww3347(新来的)回复于 2006-08-30 17:32:25 得分 0

穷举的可能性有:  
  1.   A   100X2   +B   200X2   +C   200X2  
  2.   A   100X1   +B   200X2   +C   500X1  
  3.   A   200X1   +B   200X2   +C   200X1  
  ...........  
  同时各算出以上的奖券金额.取奖券金额最大的一组.  
  --------------  
  嘻嘻,穷举一下看看一共多少种。这个穷举算法怎么写?Top

14 楼ww3347(新来的)回复于 2006-08-30 17:34:46 得分 0

1.付款金额最大可能分配出去,计算可得奖券  
  2.j9988(j9988)的方法计算可得奖券  
  两者取最大  
  ---------------  
  400   送   450  
  300   送   300  
  200   送   180  
  100   送   90  
  95     送   95  
   
  500   元现金,送吧:)Top

15 楼j9988(j9988)回复于 2006-08-30 17:38:57 得分 0

首先,  
  我已经说过了,先算出每种可能出的券别.这样再穷举.并不是说一定要出现.只是可能出现.  
   
  这种穷举用SQL不难.只要数一个while循环就行.具体算法当然得根据奖券分类来做具体的优化.  
   
  比如出现1元奖1毛.你买10万元现金那不惨了.  
   
   
   
  Top

16 楼j9988(j9988)回复于 2006-08-30 17:43:01 得分 0

两者取最大  
  ---------------  
  400   送   450  
  300   送   300  
  200   送   180  
  100   送   90  
  95     送   95  
   
  500   元现金,送吧:)  
  如果500元现金分配买这一种商品.且这种商品有这么多方案.很好算的.这不是问题Top

17 楼specialsoldier(雪地撒野~噢姐姐,我要回家)回复于 2006-08-30 17:44:40 得分 0

比如出现1元奖1毛.你买10万元现金那不惨了.  
  -----------------  
  具体的优化说得也是.不过要真是出现1元奖1毛也不惨的.先将其他所有段的回报率算出来,当大于0.1的时候就不考虑1元奖1毛.要小于等于就换吧...因为此时1元是最小金钱单位  
   
  要出现1元奖1毛,3毛奖1分就爽歪了Top

18 楼j9988(j9988)回复于 2006-08-30 17:46:07 得分 0

你说得对,是啊.得根据情况做具体的优化.考虑极端情况出现.Top

19 楼j9988(j9988)回复于 2006-08-30 17:46:46 得分 0

不聊天了,得上班.Top

20 楼ww3347(新来的)回复于 2006-08-30 17:47:31 得分 0

j9988老大写个简单的穷举模型来看看,我学习一下:)  
   
  那个例子是针对toto1980(^涛^)   提出的方案做的,最优的是   300+95+95   ,既不是你的方案,也不是付款金额最大可能分配出去:)Top

21 楼fattycat(最爱胖猫)回复于 2006-08-30 18:08:09 得分 0

 
  markTop

22 楼aruisi()回复于 2006-08-30 19:34:38 得分 0

jfTop

23 楼redwoodschu(一觉睡到太阳下山zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)回复于 2006-08-30 21:50:19 得分 0

这个有点像内存碎片分配的算法。。。  
   
   
   
  Top

24 楼redwoodschu(一觉睡到太阳下山zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz)回复于 2006-08-30 22:15:13 得分 0

 
  先计算每种商品的每种回馈模式的赠券回报率  
  再按回报率高低排序,分别是  
         
  回报率6.15       B,400送65券一张  
  回报率6.67       B,200送30券一张;A,200送30券一张  
  回报率8.33       C,500送60券一张  
  回报率10           C,现金200送20券一张;A,现金100送10券一张  
  加权后回报率是7.96  
   
  比如最简单的最大化的分配就是  
  在总金额〈850的情况下,计算出总点券是400*2,一共130点  
  浪费50元,乘加权后的回报率就是浪费了的点券,是6.3点  
  130/(130+6.3)就是点券的利用率  
  顾客最大化原则最后比较的实际上是点券的利用率  
   
   
  不知道这样的想法是否有误,请大家指教  
  Top

25 楼greenoldman()回复于 2006-08-30 22:22:31 得分 0

谁有最优算法???  
  Top

26 楼j9988(j9988)回复于 2006-08-30 23:17:59 得分 0

to   ww3347(新来的):   你对楼主的需求只理解一半.  
  针对你的出题,比楼主的需求简单多了.   况且你所认的为最优方案也是错的.  
   
  我随便写一个:  
   
   
  set   nocount   on  
   
  declare   @a   table(id   int   identity,m   int,p   int)  
  insert   @a(m,p)   select   400,450  
  union   all   select   300,300  
  union   all   select   200,180  
  union   all   select   100,90  
  union   all   select   95,95  
   
  declare   @all   int  
  set   @all=500  
  declare   @i   int  
  set   @i=1  
  declare   @b   table(id   varchar(100),m   int,p   int,f   int)  
   
  insert   @b   select   ','+rtrim(id),m,p,1   from   @a   where   m<=@all  
   
   
  while   exists(select   1   from   @a   A,@b   B   where   A.m+B.m<=@all   and   B.f=@i   and   A.id>right(B.id,charindex(',',reverse(B.id))-1))  
  begin  
  insert   @b   select   B.id+','+rtrim(A.id),A.m+B.m,A.p+B.p,@i+1   from   @a   A,@b   B   where   A.m+B.m<=@all     and   B.f=@i   and   A.id>right(B.id,charindex(',',reverse(B.id))-1)  
  set   @i=@i+1  
  end  
   
  select   A.*,B.p   as   AllPay   from   @a   A,@b   B   where   charindex(','+rtrim(A.id)+',',B.id+',')>0   and   B.id   in   (select   top   1   id   from   @b   order   by   p   desc)  
   
  --结果应该545元   取400跟95   而不是300,95,95  
  id                     m                       p                       AllPay              
  -----------   -----------   -----------   -----------    
  1                       400                   450                   545  
  5                       95                     95                     545Top

27 楼j9988(j9988)回复于 2006-08-30 23:26:57 得分 0

上面和代码中两处:A.id>right(B.id,charindex(',',reverse(B.id))-1)   应改为:A.id>=right(B.id,charindex(',',reverse(B.id))-1)    
   
  所以的结果:  
    ID                               m                       p                        
  ---------------   -----------   -----------    
  ,1,5                         495                   495  
  ,1,4                         500                   490  
  ,2,5,5                     490                   490  
  ,2,4,5                     495                   485  
  ,2,4,4                     500                   480  
  ,2,3                         500                   480  
  ,5,5,5,5,5             475                   475  
  ,4,5,5,5,5             480                   470  
  ,4,4,5,5,5             485                   465  
  ,3,5,5,5                 485                   465  
  ,3,4,5,5                 490                   460  
  ,4,4,4,5,5             490                   460  
  ,4,4,4,4,5             495                   455  
  ,3,4,4,5                 495                   455  
  ,3,3,5                     495                   455  
  ,3,3,4                     500                   450  
  ,3,4,4,4                 500                   450  
  ,4,4,4,4,4             500                   450  
  ,1                             400                   400  
  ,2,5                         395                   395  
  ,2,4                         400                   390  
  ,5,5,5,5                 380                   380  
  ,4,5,5,5                 385                   375  
  ,4,4,5,5                 390                   370  
  ,3,5,5                     390                   370  
  ,3,4,5                     395                   365  
  ,4,4,4,5                 395                   365  
  ,4,4,4,4                 400                   360  
  ,3,4,4                     400                   360  
  ,3,3                         400                   360  
  ,2                             300                   300  
  ,5,5,5                     285                   285  
  ,4,5,5                     290                   280  
  ,4,4,5                     295                   275  
  ,3,5                         295                   275  
  ,3,4                         300                   270  
  ,4,4,4                     300                   270  
  ,5,5                         190                   190  
  ,4,5                         195                   185  
  ,4,4                         200                   180  
  ,3                             200                   180  
  ,5                             95                     95  
  ,4                             100                   90  
   
  自已比较吧Top

28 楼j9988(j9988)回复于 2006-08-30 23:30:57 得分 0

楼主的需求比你理解的要复杂得多.  
   
  所以我说,要跟据实例做一些算法上调整和改进.Top

29 楼ww3347(新来的)回复于 2006-08-31 09:23:32 得分 0

恩   ,对。我的错了。学到穷举的办法:)  
  楼主更复杂的一点就是每个类别还有上限,不是全排列?  
   
  我举那个例子只是针对这个算法提出的,证明这个算法是不对的。除了穷举,还有没有简单点的算法?  
  ------------------------  
  1.付款金额最大可能分配出去,计算可得奖券  
  2.j9988(j9988)的方法计算可得奖券  
  两者取最大  
  ------------------------Top

30 楼fcuandy(了此残生.)回复于 2006-08-31 10:19:29 得分 0

只能穷举.  
  跟那天那人的问题差不多.  
  表中有   20w   条记录,有字段amount,现在想删除一些数据,使剩下的数据尽可能的接近3000.    
  其实这两个题的本质是一样的.  
   
  不用穷举的话,可以用近似算法,每次取最大可能获得的赠送的办法,但获取的结果并不一定跟理论上可获的的最大值相等.     写法如下:  
   
   
  DECLARE   @t   TABLE(id   INT   IDENTITY(1,1),Type   VARCHAR(1),Require   INT,Amount   INT)  
  INSERT   @t   SELECT   'A',100,10  
  UNION   ALL   SELECT   'A',200,30  
  UNION   ALL   SELECT   'B',400,65  
  UNION   ALL   SELECT   'B',200,30  
  UNION   ALL   SELECT   'C',200,20  
  UNION   ALL   SELECT   'C',500,60  
   
  DECLARE   @Require   INT  
  SET   @Require=850  
  SELECT   IDENTITY(INT)   ID   INTO   #   FROM   sysobjects,syscolumns  
   
  DECLARE   @x   TABLE(type   VARCHAR(1),Require   INT)  
  INSERT   @x   SELECT   'A',200  
  UNION   ALL   SELECT   'B',450  
  UNION   ALL   SELECT   'C',1200  
   
  DECLARE   @m   TABLE(type   VARCHAR(1),Require   INT,Times   INT,Amount   INT)  
   
  DECLARE   @Rq   INT,@Tm   INT,@Am   INT,@Tp   VARCHAR(1)  
  WHILE   @Require>0  
  BEGIN  
  SELECT   a.*,b.ID   Times    
  INTO   #1  
  FROM   @t   a  
  INNER   JOIN  
  (SELECT   MAX(a.Amount*b.id)   ma,a.type    
  FROM   @t   a  
  INNER   JOIN   #   b  
  ON   a.Require*b.ID   <=(SELECT   Require   FROM   @x   WHERE   a.type=type)   AND   a.Require*b.ID<=@Require  
  GROUP   BY   a.Type)     x  
  ON   a.type=x.type  
  INNER   JOIN   #   b  
  ON   b.id*a.Amount=x.ma  
   
  SELECT   @Tp=Type,@Rq=Require,@Am=Amount,@Tm=Times  
  FROM   #1  
  WHERE   Amount=(SELECT   MAX(Amount)   FROM   #1)  
   
  SET   @Require=@Require-@Rq*@Tm  
  IF   @Require>0    
  INSERT   @m   SELECT   @Tp,@Rq,@Tm,@Am  
  UPDATE   @x   SET   Require=Require-@Rq*@Tm   WHERE   Type=@Tp  
   
  DROP   TABLE   #1  
  END  
  SELECT   *   FROM   @m  
  DROP   TABLE   #  
   
  /*结果  
  Type Require Times Amount  
  B 400 1 65  
  A 200 1 30  
  C 200 1 20  
  */  
  结果说明:  
  用   400元付   B类   一次,获   65  
  用   200元付   A类   一次,获   30  
  用   200元付   C类   一次,获   20  
  剩余50元没满足任何条件,任意支付.共获得   115    
   
  楼主可以将测试数据,比如A类物品购买花400元看看,那么此时就是用400元去付A类物品2次,剩余50元不满足任何条件,任意支付,共获得   125  
   
  上面已经说明了,得出的结果并不一定是理论上最大的可获取的值.Top

31 楼fcuandy(了此残生.)回复于 2006-08-31 10:33:35 得分 0

SELECT   @Tp=Type,@Rq=Require,@Am=Amount,@Tm=Times  
  FROM   #1  
  WHERE   Amount=(SELECT   MAX(Amount)   FROM   #1)  
   
  这句稍稍更正一下,加上   ORDER   BY   Require*Times   DESC  
  以付最少的钱获得最大的赠送Top

32 楼prcgolf(小鸟)回复于 2006-09-12 14:40:27 得分 0

upTop

相关问题

关键词

得分解答快速导航

  • 帖主:tzlhr

相关链接

  • SQL Server类图书

广告也精彩

反馈

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