1. 如图所示的地图着色问题共有多少个解?如果是四色有多少个解?如果只有两色呢?
class node:
def __init__(self, name) -> None:
self.color = ""
self.colorlist = []
self.adjacent = []
self.name = name
def map(color_num):#传入颜色数量
nodelist = []
wa = node('wa'); nt = node('nt'); sa = node('sa'); q = node('q')
nsw = node('nsw'); v = node('v'); t = node('t')
wa.adjacent.append(nt);wa.adjacent.append(sa)
nt.adjacent.append(wa);nt.adjacent.append(q);nt.adjacent.append(sa)
sa.adjacent.append(wa);sa.adjacent.append(nt);sa.adjacent.append(q)
sa.adjacent.append(nsw);sa.adjacent.append(v)
q.adjacent.append(nt);q.adjacent.append(sa);q.adjacent.append(nsw)
nsw.adjacent.append(q);nsw.adjacent.append(sa);nsw.adjacent.append(v)
v.adjacent.append(sa);v.adjacent.append(nsw)
nodelist.append(sa)
nodelist.append(nt)
nodelist.append(q)
nodelist.append(nsw)
nodelist.append(wa)
nodelist.append(v)
nodelist.append(t)
for i in nodelist:
for j in range(color_num):
i.colorlist.append(j)
return nodelist
def dfs(nodelist, now_node):
if(now_node == len(nodelist)):#有界
return 1
if(len(nodelist[now_node].colorlist) == 0):#该分支无解
return 0
ret = 0
for color in nodelist[now_node].colorlist:#对该点的颜色遍历
nodelist[now_node].color = color#假定用这个颜色
l = []
count = 0
for node in nodelist[now_node].adjacent:#检验是否冲突
if color in node.colorlist:#若相邻点都有这个颜色
node.colorlist.remove(color)#删去相邻点改颜色
l.append(count)
count+=1#计数+1
ret += dfs(nodelist, now_node+1)#进行去除颜色之后的dfs
#这样的好处就是
#直接从邻接颜色删去选的颜色,就不需要再开一个dfs来区分是否使用新颜色
for i in l:
nodelist[now_node].adjacent[i].colorlist.append(color)
#出栈,把颜色加回去
return ret
for i in range(2,5):
nodeList = map(i)
print(i," ",dfs(nodeList, 0))
通过程序发现:
两种颜色 0种方案
三种颜色 18种方案
四种颜色 768种方案
2. 考虑下述的逻辑问题:有5所不同颜色的房子,住着5个来自不同国家的人,每个人都喜欢一种不同牌子的糖果,不同牌子的饮料和不同的宠物。给定下列已知事实,请回答问题“斑马住在哪?哪所房子里的人喜欢喝水?
• 英国人住在红色房子里。
• 西班牙人养狗
• 挪威人住在最左边的第一所房子里
• 绿房子是象牙色房子的右边邻居
• 喜欢抽hershey牌巧克力的人住在养狐狸的人的旁边
• 住在黄色房子里的人喜欢Kit Kats糖果
• 挪威人住在蓝房子旁边
• 喜欢smarties糖果的人养了一只蜗牛
• 喜欢Snickers 糖果的人喝橘汁
• 乌克兰人喝茶
• 日本人喜欢Milky Ways糖果
• 喜欢Kit Kats糖果的人住在养马人的隔壁
• 住在中间房子里的人喜欢喝牛奶
• 绿房子的主人喝咖啡
把这个问题表示成CSP问题,并进行求解。
- 有人喝水和养斑马 (14,10,13,11,12推断出挪威喝水,且马应该是斑马)
- 英国人–红色 //
- 西班牙人–狗 //
- 挪威人–左边第一所。 (直接的信息->1)
- 绿房子–象牙的右边 //【无法确定象牙在3还是4,假定在3找出满足的一种情况】
- 巧克力–狐狸旁边 //
- 黄色–KK糖果 (根据1和4、7排除得到挪威黄色->6)
- 挪威–蓝色旁 (1)
- sm糖果–蜗牛 //
- sn糖果–橘汁//
- 乌克兰–茶//
- 日本人–MW糖果//
- KK糖果–养马隔壁 (6)
- 中间–牛奶 (直接的信息->3)
- 绿房子–咖啡 //
打斜线的部分使用CSP方法得到的,而有括号的部分是确定的
位置从左到右 | |||||
---|---|---|---|---|---|
房屋款式 | 黄色 | 蓝色 | 红色 | 象牙 | 绿色 |
国籍 | 挪威人 | 乌克兰 | 英国 | 西班牙 | 日本人 |
零食 | KK | 巧克力 | sm | sn | MW |
饮料 | 喝水 | 茶 | 牛奶 | 橘汁 | 咖啡 |
宠物 | 狐狸 | 养马 | 蜗牛 | 狗 |