[讨论] kkkkkkkkkkkkkkkkkkkk

 关闭 [复制链接]
11#
 楼主| 发表于 2010-4-16 08:57 | 只看该作者

回复 #3 newkid 的帖子

N的数量级不大,只是研究下算法在数据库上的实现,谢谢你的解答

使用道具 举报

回复
12#
 楼主| 发表于 2010-4-16 09:19 | 只看该作者

回复 #7 newkid 的帖子

真的很强大。。。还有一个经典算法,那就是贪心算法,贪心算法可以实现背包问题的最优解,但不能求出0/1背包问题的最优解,不知该如何求解用贪心算法实现背包问题:

背包问题:与0/1背包问题类似,所不同的是在选择物品 i 装入背包时,可以选择物品 i 的一部分,而不一定要全部装入背包。

实例:物品id=(1,2,3)  价值Vi=(60,100,120)  重量Wi=(10,20,30)  背包容量C=50   那么最优解的答案应该是取ID1+ID2+2/3 ID3=60+100+80=240

C语言算法实现如下:

  1. #include <stdio.h>
  2. #include <iostream.h>

  3. #define MAXWEIGHT  50
  4. #define  n 3


  5. float pw[n]={0},x[n]={0};
  6. int w[n]={0},p[n]={0};

  7. void sort(int p[],int w[])
  8. {
  9.   int temp1,temp2;
  10.   float temp;
  11.   int i,j;
  12.   for(i=0;i<n;i++)
  13.   {
  14.     pw[i]=float(p[i])/w[i];
  15.   }


  16.   for(i=0;i<n-1;i++)
  17.   {
  18.     for(j=i+1;j<n;j++)
  19. {
  20.   if(pw[i]<pw[j])
  21.   {
  22.    temp=pw[i],pw[i]=pw[j],pw[j]=temp;
  23.    temp1=p[i],temp2=w[i];
  24.    p[i]=p[j],w[i]=w[j];
  25.    p[j]=temp1,w[j]=temp2;
  26.   }
  27. }

  28.   }


  29. }




  30. void GreedyKnapsack(int p[],int w[])
  31. {
  32. int m=MAXWEIGHT,i;
  33. for(i=0;i<n;i++)  x[i]=0.0;
  34.     for(i=0;i<n;i++)
  35. {
  36.   if(w[i]>m)   break;
  37.   x[i]=1.0;
  38.   m=m-w[i];
  39. }
  40. if(i<n)   x[i]=float(m)/w[i];




  41. }




  42. void main()
  43. {
  44. int i;
  45. printf("请输入每个物体的效益和重量:\n");
  46. for(i=0;i<n;i++)
  47. {
  48.   cin>>p[i]>>w[i];
  49. }
  50.     for(i=0;i<n;i++)
  51. {
  52.   printf("原物体%d的效益和重量分别为%d,%d:\n",i+1,p[i],w[i]);
  53. }
  54.     sort(p,w);
  55.     printf("\n\n\n按效益值非递增顺序排列物体:\n");
  56.     for(i=0;i<n;i++)
  57. {
  58.   printf("物体%d的效益和重量分别为%d,%d  效益值为:%f\n",(i+1),p[i],w[i],pw[i]);
  59.   
  60. }
  61. GreedyKnapsack(p,w);
  62. printf("\n\n\n最优解为:\n");
  63.     for(i=0;i<n;i++)
  64. {
  65. printf("第%d个物体要放%f:\n",i+1,x[i]);
  66. }


  67. }
复制代码

[ 本帖最后由 〇〇 于 2010-4-16 15:46 编辑 ]

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
13#
发表于 2010-4-16 15:45 | 只看该作者
学习

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
14#
发表于 2010-4-16 22:25 | 只看该作者
#9有BUG, 因为每次循环都仅仅保留最近一次连接的结果,而最佳答案不一定在最外面的一层。改用外连接,如果连接不上但是总价值最高的答案也应该留下来。

DROP TYPE t_pack FORCE;

CREATE OR REPLACE TYPE t_pack AS OBJECT (id NUMBER, total_w NUMBER, total_v NUMBER, nodes VARCHAR2(1000),cnt NUMBER)
/

CREATE OR REPLACE TYPE tb_pack AS TABLE OF t_pack
/

DECLARE
  lv_limit NUMBER := 10;
  a_pack tb_pack;
  a_pack2 tb_pack;
BEGIN

  SELECT t_pack(id,weight,val,'(id='||id||' w='||weight||' v='||val||')',0)
   BULK COLLECT INTO a_pack
    FROM pack
   WHERE weight<=lv_limit;
  
  LOOP
    SELECT t_pack(id,total_w,total_v,nodes,COUNT(id) OVER())
      BULK COLLECT INTO a_pack2
      FROM (SELECT p.id
                  ,NVL(p.weight,0) + t.total_w AS total_w
                  ,NVL(p.val,0) + t.total_v AS total_v
                  ,nodes||(CASE WHEN p.id IS NULL THEN NULL ELSE ' (id='||p.id||' w='||p.weight||' v='||p.val||')' END) AS nodes
                  ,RANK() OVER(ORDER BY NVL(p.val,0) + t.total_v DESC) AS rnk
           FROM pack p RIGHT JOIN TABLE(a_pack) t
                ON t.id<p.id
                   AND p.weight + t.total_w<=lv_limit
           )
    WHERE id IS NOT NULL OR rnk=1;

    a_pack := a_pack2;
   
    IF a_pack.COUNT=0 OR a_pack(1).cnt=0 THEN
       EXIT;
    END IF;
  END LOOP;
  
  DBMS_OUTPUT.PUT_LINE(a_pack(1).nodes||' total_v='||a_pack(1).total_v);
END;
/

使用道具 举报

回复
15#
 楼主| 发表于 2010-4-16 23:04 | 只看该作者
newkid好敬业啊,万分感谢你的解答。。。

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
16#
发表于 2010-4-16 23:18 | 只看该作者
这篇文章说贪婪法不能保证最优解:
http://www.qnr.cn/pc/erji/C/ziliao/201004/425956.html

使用道具 举报

回复
17#
 楼主| 发表于 2010-4-17 21:35 | 只看该作者

回复 #16 newkid 的帖子

贪婪算法本来就不能000求出0/1背包问题的最优解,但是可以求出背包问题的最优解,也就是当背包的物品可以取部分时,能得到最优解,以上有C语言用贪婪算法求背包问题的代码,但是不知道怎么“翻译”成PL/SQL,拜求。。。

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
18#
发表于 2010-4-17 21:56 | 只看该作者

回复 #17 爱上狮子座女孩 的帖子

用index by table代替数组
效益*数量为key输出就是排好序的
然后翻译GreedyKnapsack

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
19#
发表于 2010-4-18 10:00 | 只看该作者
其实这个贪婪法啥也没做,就是排序一下而已。把它等价的PLSQL写出来,简直是笑死人:

DECLARE
   
   TYPE t_row IS TABLE OF pack%ROWTYPE INDEX BY BINARY_INTEGER;  
   lv_p t_row;     
   
   lv_limit NUMBER := 10;    ------ 重量限制
   m NUMBER := lv_limit;

BEGIN
   SELECT * BULK COLLECT INTO lv_p FROM pack ORDER BY val/weight;

   FOR i IN 1..lv_p.COUNT LOOP
       DBMS_OUTPUT.PUT('(id='||lv_p(i).id||' w='||lv_p(i).weight||' v='||lv_p(i).val||')-------');

       IF lv_p(i).weight>m THEN
          DBMS_OUTPUT.PUT_LINE(m/lv_p(i).weight);
          EXIT;
       ELSE
          DBMS_OUTPUT.PUT_LINE(1);
          m := m - lv_p(i).weight;
       END IF;
   END LOOP;
   
END;
/

网上有一些改良版本的,比如和什么“遗传算法”混合,你搜索一下就知道了。

我把自己#14的写法再改一下,用一个内存数组就够了:
DECLARE
  lv_limit NUMBER := 10;
  a_pack tb_pack;
BEGIN

  SELECT t_pack(id,weight,val,'(id='||id||' w='||weight||' v='||val||')',0)
   BULK COLLECT INTO a_pack
    FROM pack
   WHERE weight<=lv_limit;
  
  LOOP

    SELECT CAST(MULTISET(SELECT id,total_w,total_v,nodes,COUNT(id) OVER()
                           FROM (SELECT p.id
                                       ,NVL(p.weight,0) + t.total_w AS total_w
                                       ,NVL(p.val,0) + t.total_v AS total_v
                                       ,nodes||(CASE WHEN p.id IS NULL THEN NULL ELSE ' (id='||p.id||' w='||p.weight||' v='||p.val||')' END) AS nodes
                                       ,RANK() OVER(ORDER BY NVL(p.val,0) + t.total_v DESC) AS rnk
                                FROM pack p RIGHT JOIN TABLE(a_pack) t
                                     ON t.id<p.id
                                        AND p.weight + t.total_w<=lv_limit
                                )
                         WHERE id IS NOT NULL OR rnk=1
                         )
                 AS tb_pack
                 )
    INTO a_pack
    FROM DUAL;
   
    IF a_pack.COUNT=0 OR a_pack(1).cnt=0 THEN
       EXIT;
    END IF;
  END LOOP;
  
  DBMS_OUTPUT.PUT_LINE(a_pack(1).nodes||' total_v='||a_pack(1).total_v);
END;
/

[ 本帖最后由 newkid 于 2010-4-18 10:01 编辑 ]

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
20#
发表于 2010-4-18 10:06 | 只看该作者

回复 #19 newkid 的帖子

学习

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表