python解号码球问题

这篇博客探讨了一个有趣的数学问题:如何将1-10号码的球放入不同号码的罐子中,确保每个球都不在其对应号码的罐子里。作者通过Python编程实现了暴力求解和数学归纳法的解决方案,并进行了性能对比。文章提到了错排数的概念,并指出当规模增大时,计算量会显著增加。最后,作者给出了递推公式F(n+1) = n * (F(n) + F(n-1))来描述n+1个球的号码不重复放法数量。
摘要由CSDN通过智能技术生成

题目描述:

现有十个分别标有1-10号码的球,十个分别标有1-10号码的罐子。每个球放进一个罐子里,现要求每一个球都不能放在同一号码的罐子中,请问有多少种放法?

 

1.1. codeball.py

<script type=text/javascript> function isnumbered(obj) { return obj.childNodes.length && obj.firstChild.childNodes.length && obj.firstChild.firstChild.className == 'LineNumber'; } function nformat(num,chrs,add) { var nlen = Math.max(0,chrs-(''+num).length), res = ''; while (nlen>0) { res += ' '; nlen-- } return res+num+add; } function addnumber(did, nstart, nstep) { var c = document.getElementById(did), l = c.firstChild, n = 1; if (!isnumbered(c)) if (typeof nstart == 'undefined') nstart = 1; if (typeof nstep == 'undefined') nstep = 1; n = nstart; while (l != null) { if (l.tagName == 'SPAN') { var s = document.createElement('SPAN'); s.className = 'LineNumber' s.appendChild(document.createTextNode(nformat(n,4,' '))); n += nstep; if (l.childNodes.length) l.insertBefore(s, l.firstChild) else l.appendChild(s) } l = l.nextSibling; } return false; } function remnumber(did) { var c = document.getElementById(did), l = c.firstChild; if (isnumbered(c)) while (l != null) { if (l.tagName == 'SPAN' && l.firstChild.className == 'LineNumber') l.removeChild(l.firstChild); l = l.nextSibling; } return false; } function togglenumber(did, nstart, nstep) { var c = document.getElementById(did); if (isnumbered(c)) { remnumber(did); } else { addnumber(did,nstart,nstep); } return false; } </script> <script type=text/javascript> document.write(' Toggle line numbers '); </script> Toggle line numbers
   1 # -*- coding: utf-8 -*-
   2 
   3 #号码球问题
   4 
   5 #求排列,这里采用迭代算法而非递归,
   6 #是为了得到更好的效率
   7 def P(x, y = None):
   8         """
   9         求排列数P(x, y),y默认值为x,此时取P(x),即x!
  10         """
  11         if x == 0 or y == 0:
  12                 return 1
  13 
  14         re = x
  15         i = x - 1
  16         if y == None:
  17                 l = 1
  18         else:
  19                 l = x - y
  20 
  21         while i > l:
  22                 re *= i
  23                 i -= 1
  24         return re
  25 
  26 #求组合
  27 def C(x, y):
  28         """
  29         求组合数C(x, y)
  30         """
  31         if x == y:
  32                 return 1
  33         else:
  34                 return P(x, y)/P(y)
  35 
  36 #求号码球(Code Ball)问题,CB1使用递归算法:
  37 #1、CB1算法只考虑取出所有球的情况
  38 #       即每一个罐子都有一个球对应,没有空罐。
  39 #2、CB1(0)时,视作有1种解(这种情况下没
  40 #有罐子与球对应);
  41 #3、CB1(1)时,没有解(罐子必然与球对应);
  42 #4、CB1(2)时,有一种解(罐子与球要么完全)
  43 #对应,要么完全不对应;
  44 #5、CB1(n), n>=3可以分解为用所有可能的排列减去
  45 #不合要求的组合。包含有m(m <= n)个重复对应的排
  46 #列数为C(n, m)*CB1(n - m)。m取遍n到1,
  47 #P(n)与C(n, m)*CB1(n - m)之积加和之差,即为所求。
  48 #故:
  49 #CB1(3) = P(3) - C(3, 3)*CB1(3 - 3) - C(3, 2)*CB1(3 - 2) - C(3, 1)*CB1(3 - 1) 
  50 #CB1(n) = P(n) - C(n, n)*CB1(n - n) - C(n, n - 1)*CB1(n - n + 1) - ... - C(n, 1)*CB1(n - 1)
  51 #               = P(n) - C(n, n)*CB1(0) - C(n, n - 1)*CB1(1) - ... - C(n, 1)*CB1(n - 1)
  52 #由C(n, n)==1,CB1(0)==CB1(2)==1,CB1(1)==0,CB1(n)可以简化为:
  53 #CB1(n)=P(n) - 1 - C(n, n - 2) - C(n, n - 3)*CB1(3) - ... - n*CB1(n-1)
  54 def CB1(x):
  55         if x == 0 or x == 2:
  56                 return 1
  57         elif x == 1:
  58                 return 0
  59         else:
  60                 re = P(x) - 1
  61                 for i in range(2, x):
  62                         re -= C(x, x-i)*CB1(i)
  63                 return re
  64 
  65 print "CB1算法解得CB1(10) = ", CB1(10)

2. Zoom.Quiet

坚决使用暴力!

使用"一切从游戏开始 - ChinesePython Wiki"的技巧来优化

2.1. codeBall.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值