鱼C论坛

 找回密码
 立即注册
楼主: jerryxjr1220

[技术交流] 三种不同算法求解八皇后问题:排列组合、回溯法+递归、生成器+递归

[复制链接]
发表于 2020-3-17 21:54:43 | 显示全部楼层
排列组合确实慢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-28 16:42:58 | 显示全部楼层
牛逼嗷
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-2 17:15:23 | 显示全部楼层
学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-7 07:47:53 | 显示全部楼层
想知道
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-2 03:00:14 | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-6-2 13:21:06 | 显示全部楼层
本帖最后由 java2python 于 2020-6-3 01:16 编辑

达人的代码太精简了,里面的yield就不懂,用了他的conflict函数,写了一个非递归的:
  1. def conflict(cur_row, row_ptr):
  2.         for i in range(cur_row):
  3.                 if abs(row_ptr[i] - row_ptr[cur_row]) in (0, cur_row - i):
  4.                         return True
  5.         return False

  6. def solve(QUEEN_SUM):
  7.     row_ptr = [0]*QUEEN_SUM
  8.     cur_row = 0
  9.     while(True) :
  10.         while(row_ptr[cur_row] == QUEEN_SUM or conflict(cur_row,row_ptr)):
  11.             if(row_ptr[cur_row] == QUEEN_SUM):
  12.                 cur_row -= 1
  13.             if(cur_row < 0 ):
  14.                 return
  15.             row_ptr[cur_row] += 1
  16.         if(cur_row ==QUEEN_SUM-1) :
  17.             chest = [[0]*QUEEN_SUM for i in range(QUEEN_SUM)]
  18.             for i in range(QUEEN_SUM):
  19.                     chest[i][row_ptr[i]] = 1
  20.                     print (chest[i])
  21.             print ()
  22.             row_ptr[cur_row] += 1
  23.         else:
  24.             cur_row += 1
  25.             row_ptr[cur_row] = 0

  26. solve(8)
复制代码


yield看了网上的知识,还是半懂不懂,有点超出理解范围,做了一个没有yield的版本,对比代码,总算大致知道意思,yield是同一层的结果扔到turple后再return:
  1. def conflict(state, nextX):
  2.     nextY = len(state)
  3.     for i in range(nextY):
  4.         if abs(state[i] - nextX) in (0, nextY - i):
  5.             return True
  6.     return False

  7. def queens(num = 3, state = (),cfloor=0):
  8.     res = None        #这里要res要初始化
  9.     for pos in range(num):
  10.         if not conflict(state, pos):
  11.             #if len(state) == num - 1:
  12.             #        yield (pos,)
  13.             if len(state) == num - 1:
  14.                 return ((pos,),)
  15.             else:
  16.                 #for result in queens(num, state + (pos,)):
  17.                 #        yield (pos,) + result
  18.                 result = queens(num, state + (pos,),cfloor+1)
  19.                 if result == None:       #这里要None判别
  20.                     continue
  21.                 for ren in result:
  22.                     if res == None:      #这里要None判别
  23.                         res = (((pos,) + ren),)
  24.                     else:
  25.                         res =  (((pos,) + ren),) + res
  26.     return res
  27. c = 0
  28. result = queens(6,(),0)
  29. for res in result:
  30.         c+=1
  31.         print ('Solution %d: ' % c)
  32.         chest = [[0]*len(res) for i in range(len(res))]
  33.         for i in range(len(res)):
  34.                 chest[i][res[i]] = 1
  35.                 print (chest[i])
  36.         print ()        
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-2 14:03:08 | 显示全部楼层
本帖最后由 java2python 于 2020-6-2 14:51 编辑

八皇后全排列做法(一共是16777216组合,如果找到第一个布局就跳出,就10秒,全部的话3分多钟):
  1. pows = [pow(8,0),pow(8,1),pow(8,2),pow(8,3),pow(8,4),pow(8,5),pow(8,6),pow(8,7),pow(8,8)]

  2. def check(rows):
  3.     for row in range(1,8):
  4.         for i in range(row):
  5.             if abs(rows[i] - rows[row]) in (0, row - i):
  6.                 return True
  7.     return False

  8. rows = [0]*8
  9. for sts in range(0,pow(8,8)):
  10.     for bit in range(0,8):
  11.         rows[bit]=(sts%pows[bit+1])//pows[bit]
  12.     if check(rows) == False:
  13.         chest = [[0]*8 for i in range(8)]
  14.         for i in range(8):
  15.             chest[i][rows[i]] = 1
  16.             print (chest[i])
  17.         print ()
  18.         #break
复制代码


当然全排列太慢了,不过可以稍作改进,就和快速搜索是一样速度了(当然每一位用pows取余数再除,会多一点时间,不过没有数量级的区别),就是检测局面的时候,哪一行出问题(check函数返回true,false改为行号,如果是0,就是原来的false),那么就直接进入这一行的下一个选项(这一行已经出问题,后面的排列搜索全是无用功,实际逻辑和快速搜索一样,不过全排列的程序是最容易理解的):
  1. pows = [pow(8,8),pow(8,7),pow(8,6),pow(8,5),pow(8,4),pow(8,3),pow(8,2),pow(8,1),pow(8,0)]

  2. def check(rows):
  3.     for row in range(1,8):
  4.         for i in range(row):
  5.             if abs(rows[i] - rows[row]) in (0, row - i):
  6.                 return row
  7.     return 0

  8. rows = [0]*8
  9. sts = 0
  10. while sts < pow(8,8):
  11.     for bit in range(0,8):
  12.         rows[bit]=(sts%pows[bit])//pows[bit+1]
  13.     err_row = check(rows)
  14.     if err_row == 0:
  15.         chest = [[0]*8 for i in range(8)]
  16.         for i in range(8):
  17.             chest[i][rows[i]] = 1
  18.             print (chest[i])
  19.         print ()
  20.         sts += 1
  21.     else:
  22.         sts += pows[err_row+1]
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-11-23 20:21:18 | 显示全部楼层
那份开始开始疯狂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-12-1 20:58:07 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-28 11:00:18 | 显示全部楼层
嗷嗷嗷
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-4-4 18:45:54 | 显示全部楼层
谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-5-2 00:11:40 | 显示全部楼层
要看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-5-4 13:50:49 From FishC Mobile | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-12-4 17:19:09 | 显示全部楼层
666
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-12-7 23:30:17 | 显示全部楼层
666
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-15 01:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表