四男两女三间房,房间不能空,男女不同室,有多少分组方案?

知乎上的题目,号称难题,其实数学方法并不难。不过要枚举列出所有方案,还是需要找个合适的算法。
凑个热闹,写了一段 fortran ,并改写成 Python。核心算法是以三进制数来模拟(枚举)分组方案,检验合法的,计数、输出。


fortran 代码
! fortran
! 2024-07-01
! szw_sh@163.com


integer :: a(6),b(3)
character(2) :: s(6)=(/'a1','a2','a3','a4','b1','b2'/)

aa: do i=0,3**6-1                               ! 用三进制数模拟分组

  ii=i
  b=0
  do j=6,1,-1
    k=mod(ii,3)+1
	  a(j)=k
	  b(k)=b(k)+1
	  ii=ii/3
	  if(j.lt.5.and.(k.eq.a(5).or.k.eq.a(6))) cycle aa
  end do
  if(minval(b).eq.0) cycle

  m=m+1                                         ! 计数
  write(*,'(a$)') '('                           ! 输出具体分组的情况
  do j=1,3
    n=0
	  do k=1,6
	    if(a(k).ne.j) cycle
	    if(n.eq.1) write(*,'(a$)') '+'
	    write(*,'(a$)') s(k)
	    n=1
    end do
	  if(j.lt.3) write(*,'(a$)') ','
  end do
  write(*,'(a$)') '), '
  if(mod(m,3).eq.0) write(*,*)

end do aa

write(*,'(a,g0)') 'total = ',m                   ! 输出总数

end
        

Python 代码
# Python
# 2024-07-02
# szw_sh@163.com

a = [0] * 6  # 初始化数组
b = [0] * 3
s = ['a1', 'a2', 'a3', 'a4', 'b1', 'b2']
m = 0  # 计数器

for i in range(3**6):  # 使用三进制数模拟分组
    
  ii = i
  b = [0] * 3
  for j in range(5, -1, -1):
    k = (ii % 3) 
    a[j] = k
    b[k] += 1
    ii //= 3
    if j<4  and (k==a[4] or k==a[5]):
      b = [0] 
      break

  if min(b) == 0:
    continue

  m += 1
  print('(', end='')  # 输出具体分组
  for j in range(3):
    n = 0
    for k in range(6):
      if a[k] != j:
        continue
      if n == 1:
        print('+', end='')
      print(s[k], end='')
      n = 1
    if j < 2:
      print(',', end='')
  print('), ', end='')
  if m % 3 == 0:
    print()  # 换行

print(f'total = {m}')  # 输出总数

计算结果
(a1+a2+a3+a4,b1,b2), (a1+a2+a3+a4,b2,b1), (a1+a2+a3,a4,b1+b2), 
(a1+a2+a3,b1+b2,a4), (a1+a2+a4,a3,b1+b2), (a1+a2,a3+a4,b1+b2), 
(a1+a2+a4,b1+b2,a3), (a1+a2,b1+b2,a3+a4), (a1+a3+a4,a2,b1+b2), 
(a1+a3,a2+a4,b1+b2), (a1+a4,a2+a3,b1+b2), (a1,a2+a3+a4,b1+b2), 
(a1+a3+a4,b1+b2,a2), (a1+a3,b1+b2,a2+a4), (a1+a4,b1+b2,a2+a3), 
(a1,b1+b2,a2+a3+a4), (a2+a3+a4,a1,b1+b2), (a2+a3,a1+a4,b1+b2), 
(a2+a4,a1+a3,b1+b2), (a2,a1+a3+a4,b1+b2), (a3+a4,a1+a2,b1+b2), 
(a3,a1+a2+a4,b1+b2), (a4,a1+a2+a3,b1+b2), (b1,a1+a2+a3+a4,b2), 
(b2,a1+a2+a3+a4,b1), (b1+b2,a1+a2+a3,a4), (b1+b2,a1+a2+a4,a3), 
(b1+b2,a1+a2,a3+a4), (b1+b2,a1+a3+a4,a2), (b1+b2,a1+a3,a2+a4), 
(b1+b2,a1+a4,a2+a3), (b1+b2,a1,a2+a3+a4), (a2+a3+a4,b1+b2,a1), 
(a2+a3,b1+b2,a1+a4), (a2+a4,b1+b2,a1+a3), (a2,b1+b2,a1+a3+a4), 
(b1+b2,a2+a3+a4,a1), (b1+b2,a2+a3,a1+a4), (b1+b2,a2+a4,a1+a3), 
(b1+b2,a2,a1+a3+a4), (a3+a4,b1+b2,a1+a2), (a3,b1+b2,a1+a2+a4), 
(b1+b2,a3+a4,a1+a2), (b1+b2,a3,a1+a2+a4), (a4,b1+b2,a1+a2+a3), 
(b1+b2,a4,a1+a2+a3), (b1,b2,a1+a2+a3+a4), (b2,b1,a1+a2+a3+a4), 
total = 48

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值