1、八皇后
国际象棋中的棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则
这八个皇后如何相安无事的放置在棋盘上呢?1970年与1971年, E.W.Dijkstra与N.Wirth曾经用这
个问题来讲解程式设计之技巧。
使用递归可以解决这个问题,但如何减少递归次数呢?在八皇后问题中如果检查了某列,则该列的其他格子就不需要检查了,这个方法称之为分支修剪。
实现方式:
N = 8
# 同栏是否有皇后,1表示有
column = [0 ]* (N+1)
# 右上至左下是否有皇后
rup = [0]*(2*N+1)
# 左上至右下是否有皇后
lup = [0]*(2*N+1)
queen = [0] * (N+1)
def showAnswer():
print('解答次数')
for y in range(1,N+1):
for x in range(1,N+1):
if queen[y] == x:
print('Q', end='')
else:
print(" .", end='')
print(' ')
def backtrack(i):
if i>N:
showAnswer()
else:
for j in range(1,N+1):
if column[j] == 1 and rup[i+j] == 1 and lup[i-j+N] == 1:
queen[i] = j
column[j] = rup[i+j] = lup[i-j+N] = 0
backtrack(i+1)
column[j] = rup[i+j] = lup[i-j+N] = 1
if __name__ == '__main__':
for i in range(1,N+1):
column[i] = 1
for i in range(1,2*N+1):
rup[i] = lup[i] = 1
backtrack(1)
2、生命游戏
生命游戏(game of life)为1970年由英国数学家J. H. Conway所提出,某一细胞的邻居包括上、 下、左、右、左上、左下、右上与右下相邻之细胞,游戏规则如下: 孤单死亡:如果细胞的邻居小于一个,则该细胞在下一次状态将死亡。 拥挤死亡:如果细胞的邻居在四个以上,则该细胞在下一次状态将死亡。 稳定:如果细胞的邻居为二个或三个,则下一次状态为稳定存活。 复活:如果某位置无细胞存活,而该位置的邻居为三个,则该位置将复活一细胞。
实现:
MAXROW = 10
MAXCOL = 25
DEAD = 0
ALIVE = 1
map = [[0 for _ in range(MAXCOL)] for _ in range(MAXROW)]
newmap = [[0 for _ in range(MAXCOL)] for _ in range(MAXROW)]
def copyMap():
for row in range(MAXROW):
for col in range(MAXCOL):
map[row][col] = newmap[row][col]
a = 3
def outputMap():
print("Game of life cell status")
for row in range(MAXROW):
print(' ');
for col in range(MAXCOL):
if map[row][col] == ALIVE:
print("# ", end="")
else:
print("- ", end="")
def neighbors(row, col):
count = 0
for r in range(row - 1, row + 2):
for c in range(col - 1, col + 2):
if r < 0 or r >= MAXROW or c < 0 or c >= MAXCOL:
continue
elif map[r][c] == ALIVE:
count += 1
if map[row][col] == ALIVE:
count -= 1
return count
def init():
for row in range(MAXROW):
for col in range(MAXCOL):
map[row][col] = DEAD
print("Game of life Program")
print("0 <= x <= {}, 0 <= y <= {}".format(MAXROW - 1, MAXCOL - 1))
print("Terminate with x, y = -1, -1")
while 1:
row = int(input("请输入第一个数字"))
col = int(input("请输入第二个数字"))
if 0 <= row and row < MAXROW and 0 <= col and col < MAXCOL:
map[row][col] = ALIVE
elif row == -1 or col == -1:
break
else:
print("(x, y) exceeds map ranage!")
if __name__ == '__main__':
init()
while 1:
outputMap()
for row in range(MAXROW):
for col in range(MAXCOL):
count = neighbors(row, col)
if count == 0 or count==1 or count==4 or count==5 or count==6 or count==7 or count == 8:
newmap[row][col] = DEAD
break
elif count==2:
newmap[row][col] = map[row][col]
break
elif count==3:
newmap[row][col] = ALIVE
break
copyMap()
print("Continue next Generation ? ")
ans = input("是否继续(Y):")
if ans != 'Y':
break
3、双色、三色河内塔
3.1、双色河内塔
双色河内塔如下图将两个颜色最终分开存放,首先将黄色移动到第一个柱子,再将蓝色移动到第
三个柱子,然后递归处理就可以了
def hanoi(disks, source, temp, target):
if disks == 1:
print("move disk from {} to {}".format(source, target))
print("move disk from {} to {}".format(source, target))
else:
hanoi(disks-1,source, target, temp)
hanoi(1,source, temp, target)
hanoi(disks-1, temp, source, target)
def hanoi2colors(disks):
source = 'A'
temp = 'B'
target = 'C'
for i in reversed(range(2,int(disks / 2)+1)):
hanoi(i-1, source, temp, target)
print("move disk from {} to {}".format(source, temp))
print("move disk from {} to {}".format(source, temp))
hanoi(i-1, target, temp, source)
print("move disk from {} to {}".format(temp, target))
print("move disk from {} to {}".format(source, temp))
print("move disk from {} to {}".format(source, target))
if __name__ == '__main__':
n = input("请输入盘数:")
hanoi2colors(int(n))
3.2、三色河内塔
三色河内塔处理方式跟双色类似,首先移动将前面的黄色和蓝色分别移动到第二和第三根柱
子上,然后递归处理
实现:
def hanoi(disks, source, temp, target):
if disks == 1:
print("move disk from {} to {}".format(source, target))
print("move disk from {} to {}".format(source, target))
print("move disk from {} to {}".format(source, target))
else:
hanoi(disks-1,source, target, temp)
hanoi(1,source, temp, target)
hanoi(disks-1, temp, source, target)
def hanoi3colors(disks):
source = 'A'
temp = 'B'
target = 'C'
if disks == 3:
print("move disk from {} to {}".format(source, temp))
print("move disk from {} to {}".format(source, temp))
print("move disk from {} to {}".format(source, target))
print("move disk from {} to {}".format(temp, target))
print("move disk from {} to {}".format(temp, source))
print("move disk from {} to {}".format(target, temp))
else:
hanoi(disks/3-1,source, temp, target)
print("move disk from {} to {}".format(source, temp))
print("move disk from {} to {}".format(source, temp))
print("move disk from {} to {}".format(source, temp))
hanoi(disks/3-1,target, temp, source)
print("move disk from {} to {}".format(temp, target))
print("move disk from {} to {}".format(temp, target))
print("move disk from {} to {}".format(temp, target))
hanoi(disks/3-1,source, target, temp)
print("move disk from {} to {}".format(target, source))
print("move disk from {} to {}".format(target, source))
hanoi(disks/3-1, temp, source, target)
print("move disk from {} to {}".format(source, temp))
for i in reversed(range(1,int(disks / 3))):
if i>1:
hanoi(i-1, target, source, temp)
print("move disk from {} to {}".format(target, source))
print("move disk from {} to {}".format(target, source))
if i>1:
hanoi(i-1, temp, source, target)
print("move disk from {} to {}".format(source, temp))
if __name__ == '__main__':
n = input("请输入盘数:")
hanoi3colors(int(n))
4、蒙地卡罗法求PI
蒙地卡罗为摩洛哥王国之首都,该国位于法国与义大利国境,以赌博闻名。蒙地卡罗的基本原理为以乱 数配合面积公式来进行解题,这种以机率来解题的方式带有赌博的意味,虽然在精确度上有所疑虑,但其解题 的思考方向却是个值得学习的方式。
蒙地卡罗的解法适用于与面积有关的题目,例如求PI值或椭圆面积,以PI值为例:假设有一个
圆半径为1,所以四分之一圆面积就为PI,而包括此四分之一圆的正方形面积就 为1,如下图所
示:
如果随意的在正方形取点,则这些点有些会落于四分之一圆内,假设所取得点有
n点
,在圆内
的有c点,则依比例来算,就会得到上图中最 后的公式。 至于如何判断所产生的点落于圆内,很简
单,取
X
与Y两个数值,如果X^2+Y^2
等于1就是落在圆内。
实现:
import random
N = 50000
sum = 0
for i in range(N):
x = random.random()
y = random.random()
if (x * x + y * y) < 1:
sum += 1
print("PI = {}".format(4 * sum / N))
5、筛选求质数
除了自身之外,无法被其它整数整除的数称之为质数。求质数有很多种方式,这里介绍
Eratosthenes求质数方法。
假设要求质数的数是N
,则只要计算至
N的开根号就可以了,道理很简单,假设 A*B = N
,如
果
A
大于
N
的开根号,则小于
A
之前的就到
B这个数可以整除
N
。不过在代码里使用开根号会有精确
度的问题,所以可以使用
i*i <= N
进行计算,且执行更
快 。
再考虑一个问题,如:2 3 4 5 6 7 8 9 10 .。。。N,首先将2得倍数剔除,变成:2 3 5 7 9
.。。。N,再将3的倍数剔除,变成:2 5 7 .。。。N,依次将5的倍数,7的倍数等等剔除,最后
剩下的就是质数,这就是
Eratosthenes方法。
实现:
N = 1000
prime = [0]*(N+1)
for i in range(2,N+1):
prime[i] = 1
i = 2
while i*i<=N:
if prime[i] == 1:
j = 2*i
while j <= N:
if j%i==0:
prime[j] = 0
j += 1
i += 1
for i in range(2,N):
if prime[i] == 1:
print("{} ".format(i),end="")
if i%16==0:
print("")