父亲需要些1分、2分、3分、5分、10分的邮票,其中两种各买四张,另外的三种各买三张。我忘记是具体张数是如何分配的,只知道他给了我一些10分硬币, 金额刚好买这些邮票。 方法1:笛卡儿积 总共有5种邮票,每种的数目都为3或4.用笛卡儿积求出数目的所有组合,并且从中筛选出总面值可以被10整除的,并且数目4出现两次,数目3出现3次的那些组合。 with c as (select 3 cnt from dual union all select 4 from dual),--邮票数目 stamps as (select c1.cnt || c2.cnt || c3.cnt || c5.cnt || c10.cnt as all_cnt,--把5种邮票的数目串起来 c1.cnt + c2.cnt * 2 + c3.cnt * 3 + c5.cnt * 5 + c10.cnt * 10 as val,--总面值 '1*' || c1.cnt || '+2*' || c2.cnt || '+3*' || c3.cnt || '+5*' || c5.cnt || '+10*' || c10.cnt as result --用字符串表示的组合结果 from c c1, c c2, c c3, c c5, c c10) select result || '=' || val from stamps where mod(val, 10) = 0 --总面值必须是10的倍数 and regexp_count(all_cnt, '3') = 3 --数目3出现了3次 and regexp_count(all_cnt, '4') = 2 ;--数目4出现了2次 方法2:把5种邮票的数据做一个全排列 因为数目仅有两种,全排列的结果中会有很多重复的,用distinct把重复值去除。 with stamps as --构造出一个包含了所有邮票面值及所有张数的集合 (select rownum rn, (case when rownum in (1, 2) then 4 else 3 end) as cnt,--4张的有2行,3张的有2行 decode(rownum, 4, 5, 5, 10, rownum) val --每种邮票的面值 from dual connect by rownum <= 5), t1 as --集合t1利用组合的方式求全排列,最后加上distinct去除重复结果 (select distinct replace(sys_connect_by_path(cnt, ','), ',') all_cnt from stamps where level = 5 connect by nocycle rn <> prior rn and level < = 5), t2 as --把求出的邮票张数和面值进行一一对应 (select id, to_number(substr(all_cnt, stamps.rn, 1)) cnt, --把张数的一个排列拆开为5行 stamps.val --每行对应的面值 from (select rownum id, all_cnt from t1), --为每种排列取一个唯一的ID stamps) select * from ( select t2.id, cnt,val, sum(cnt * val) over(partition by id) total --用sum求出每种组合的总面值,id为每种组合的唯一标识,每个id对应t1的1行,t2的5行 from t2 ) where mod(total,10)=0 order by id,val; 方法3:用递归with with t(lvl,val,left_4,left_3,result) as (--结构:递归层数,总面值,数目为4的邮票种数,数目为3的邮票种数 select 0,0,2,3,'' from dual --初始化结果集:开始数目为4的邮票可有2种,数目为3的邮票可有3种 union all select t.lvl+1, --加入一种邮票 t.val+s.price*cnt, --总面值递增 left_4-decode(cnt,4,1,0),--如果加入的张数为4,则数目为4的邮票种数递减 left_3-decode(cnt,3,1,0),--如果加入的张数为3,则数目为3的邮票种数递减 t.result||' '||s.price||'*'||cnt from t, (select rownum price_id,decode(rownum,4,5,5,10,rownum) as price from dual connect by rownum<=5) s,--所有5种面值 (select 4 as cnt from dual union all select 3 from dual ) --每种面值可能的张数 where t.lvl+1 = s.price_id --连接条件:新加入第n种邮票,n为1至5 and (cnt = 4 and left_4>0 or cnt =3 and left_3>0) --如果种数未减至0,则该数目可以出现 ) select result||'='||val from t where lvl =5 and mod(val,10)=0; --最后筛选条件:5种齐全而且总面值为10的整数倍 总结:前2种方法比较容易理解,第3种方法有些抽象,需要理解递归的思想,但思路还是很巧妙的,可以做作解决问题的创新思维。
邮票谜题
来源:这里教程网
时间:2026-03-03 12:58:14
作者:
编辑推荐:
- 邮票谜题03-03
- Oracle 表空间和数据文件03-03
- Oracle的SCN显示问题03-03
- 打开Word提示您正视图运行的函数包含有宏或需要宏语言支持的内容的解决方法03-03
- 用WORD写论文时好用到哭的技巧-添加注释03-03
- 使用Word制作鱼骨流程图的方法03-03
- Word排序功能:Word 2010文档表格排序教程03-03
- Word文档中怎么删除由分节符导致的空白页03-03
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- Oracle的SCN显示问题
Oracle的SCN显示问题
26-03-03 - WRH$_ACTIVE_SESSION_HISTORY未自动清理导致SYSAUX空间过度增长的处理方法
- Debian监控业务指标配置(手把手教你用Prometheus+Grafana搭建Debian系统性能监控平台)
- 【kingsql分享】Oracle跨版本迁移之XTTS_V4版本的实施
【kingsql分享】Oracle跨版本迁移之XTTS_V4版本的实施
26-03-03 - PLSQL Developer 提示字段名,回车后卡顿解决
PLSQL Developer 提示字段名,回车后卡顿解决
26-03-03 - oracle 正则表达式4个主要函数
oracle 正则表达式4个主要函数
26-03-03 - 数据泵:expdp/impdp
数据泵:expdp/impdp
26-03-03 - 用listagg函数分组实现列转行
用listagg函数分组实现列转行
26-03-03 - Debian网络身份认证详解(手把手教你配置Debian系统下的企业级WiFi与有线网络身份验证)
- Oracle Exadata 存储服务器原理探究
Oracle Exadata 存储服务器原理探究
26-03-03
