栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

蓝桥杯省赛2021 回路计数 python

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

蓝桥杯省赛2021 回路计数 python

题目描述

蓝桥学院由 21栋教学楼组成,教学楼编号 1​​ 到 21。对于两栋教学楼 a​​ 和 b​,当 a​ 和 b​ 互质时,a和 b之间有一条走廊直接相连,两个方向皆可通行,否则没有直接连接的走廊。

小蓝现在在第一栋教学楼,他想要访问每栋教学楼正好一次,最终回到第一栋教学楼(即走一条哈密尔顿回路),请问他有多少种不同的访问方案?

两个访问方案不同是指存在某个 i,小蓝在两个访问方法中访问完教学楼 i后访问了不同的教学楼。

提示:建议使用计算机编程解决问题。

思路: 

状压 dp。

由于教学楼的个数很少,我们考虑用一个二进制位数等于 21的数来表示教学楼的访问状态。

对于该二进制数,如果它的第 i位(二进制下)的值为 1,则表示当前状态下第 i栋教学楼已经访问过一次了;若它的第 i 位(二进制下)的值为 0,则表示当前状态下第 ii 栋教学楼还未访问。

于是可以定义 dp[i][j] 表示当前的状态为 i,最后走到的教学楼为 j 的方案数。

那么转移方程为:

dp[i + 1 <

其中需满足对于状态 i,教学楼 k并未访问过(即 (i >> k & 1) = 0 ) 且 j,k间存在路径(g[j][k]!=0)

最后答案为 ∑​dp[(1<<21)−1][i]=881012367360(0<=i<=20)

终点可以在任意一点:因为1与任何数都互质,所以无论在哪,最终都要回到起点。

# python 跑的相当慢,不过这是道填空题就无所谓了
import math
n=1<<21
dp = [[0] * (22) for i in range(n+1)]
g = [[0 for i in range(22)] for i in range(22)]

for i in range(1, 22):
    for j in range(1, 22):
        if math.gcd(i, j) == 1:
            g[i - 1][j - 1] = g[j - 1][i - 1] = 1
dp[1][0] = 1
i = 1
while i < n:
    for j in range(0, 21):
        if (i >> j & 1) == 0:
            continue
        for k in range(0, 21):
            if g[j][k] == 0 or (i >> k & 1) != 0:
                continue
            dp[(i + (1 << k))][k] += dp[i][j]
    i += 1
res = 0
for i in range(0, 21):
    res += dp[n - 1][i]
print(res)

 

步骤:

1.建邻接表,判断两个教学楼之间是否有路

2.利用状压dp开始走

3.计算方案数

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/757482.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号