例子:
有6个颜色各不相同的水桶,其桶身和桶盖颜色相同,现在将桶身和桶盖随机打乱组合,求全部桶盖和桶身都不匹配的组合有多少种?打印所有组合。
算法思想:
不同桶盖和桶身一对一匹配,但是颜色不能一样。我们建立一个列表:里面的元素值表示桶身,元素的位置表示桶盖。
我们对桶身进行遍历,假如桶身元素值等于它的这个位置,不能取;假如不等于而且以前没有被用过,它是可以用的,我们把它的值加到列表里面,列表的长度也加1.假如列表的长度变成水桶总数,输出目前列表里面的值。
删除元素的情况有两个:
- 现在的元素满了需要删除列表最后一个元素
- 现在的元素不能满足题目要求,组不了匹配序列,也删除列表最后一个元素。(不用担心删的不够,因为我们是递归调用,所以一层一层删回去直到满足条件)
我们采用图的深度遍历方法,设置访问矩阵表示桶身的使用情况。下面是所有代码可以运行,想来看解释的话在后面。
class ColorStack:
color_list = []
length = 0
def __init__(self, length=0):
self.length = length
def push(self, x: int):
self.color_list.append(x)
self.length += 1
def pop(self):
if self.length <= 0:
return -1
var = self.color_list.pop()
self.length -= 1
return var
count = 0
def count_combinations():
for i in range(6):
color = ColorStack()
visited_color = [0 for i in range(6)]
if i != 0:
visited_color[i] = 1
color.push(i)
DFS_color(color, visited_color)
def DFS_color(color=ColorStack(), visited_color=[]):
for j in range(6):
if color.length < 6:
if visited_color[j] == 0 and (color.length - 1) != j:
visited_color[j] = 1
color.push(j)
DFS_color(color, visited_color)
if color.length == 6:
print(color.color_list)
global count
count += 1
break
var = color.pop()
visited_color[var] = 0
if __name__ == '__main__':
count_combinations()
print(count)
全部代码写完了,假如你想输出文字,在函数
def DFS_color(color=ColorStack(), visited_color=[]):
的
if color.length == 6:
print(color.color_list)
变一下对映关系,元素的值表示桶身,顺序表示桶盖,color.color_list就是类似[1,2,3,4,5,0]这样的值
下面是解释————————————————————————
我们定义了一个类ColorStack用来存颜色种类,count表示组合的所有数量
def count_combinations():
for i in range(6):
color = ColorStack()
visited_color = [0 for i in range(6)]
if i != 0:
visited_color[i] = 1
color.push(i)
DFS_color(color, visited_color)
(元素的值表示桶身,顺序表示桶盖)我们想遍历所有的情况,for i in range(6) ,这个就表示让桶盖子匹配桶身,假如第一个桶盖子和桶身颜色不一样就能继续,第一个桶盖子有5种匹配的可能,这样就包含了所有序列。
def DFS_color(color=ColorStack(), visited_color=[]):
for j in range(6):
if color.length < 6:
if visited_color[j] == 0 and (color.length - 1) != j: # 匹配成功
visited_color[j] = 1
color.push(j) # 进栈
DFS_color(color, visited_color) # 遍历下一个桶盖子
if color.length == 6:
print(color.color_list)
global count # 统计不同组合数量
count += 1
break
var = color.pop()
visited_color[var] = 0
这个是深度遍历内部的详细过程,visited_color表示桶盖子的有没有匹配成功,1表示匹配成功,0表示没有匹配成功,假如现在color.length<6,表示没完全匹配完,需要继续匹配。
break
break是因为现在的序列已经满足,所以要跳出循环,因为你也没元素能用了
var = color.pop()
visited_color[var] = 0
这里之所以放在for循环外面一方面是因为元素不能用了,另一方面假如你 j 变成 6了,在现有元素下你已经得不到符合要求的序列了,所以要出栈,让这个位置的桶盖重新变得能用,回退到上一层。
结果在下面:
D:\design_project\python_project\Scripts\python.exe D:/design_project/python_project/text.py
[1, 2, 0, 3, 4, 5]
[1, 2, 0, 4, 5, 3]
[1, 2, 0, 5, 4, 3]
[1, 2, 3, 0, 4, 5]
[1, 2, 3, 4, 0, 5]
[1, 2, 3, 4, 5, 0]
...
一共256种,有什么问题或者错误的地方大家可以互相交流一下。