数学建模练习小标题

[复制链接]
发表于 2026-1-17 20:30:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
标题A

有三名贩子各带一名仆役过河,船最多能载两人。在河的任何一岸,若仆役数超 过贩子数,仆役会杀贩子越货。怎样搭船由贩子决定,问是否有安全过河方案,如有,最少须要几步?
界说变量

贩子和仆役的状态:利用状态 (M, S) 来表现某一岸上的贩子数和仆役数。
船的状态:由于船只能在两岸之间移动,利用一个二元变量来表现船的位置,1 表现船在左岸(起始岸),0 表现船在右岸(目标岸)。
因此,体系的一个状态可以表现为三元组 (M, S, B),此中,M 表现左岸的贩子数,S 表现左岸的仆役数,B 表现船的位置(左岸或右岸),界说初始状态为 (3, 3, 1),目标状态为 (0, 0, 0),即全部人都在右岸。
状态转换

在题目标办理过程中,船一次可以带1或2人过河,因此答应的利用包罗一名贩子和一名仆役一起过河 (1, 1),两名贩子一起过河 (2, 0),两名仆役一起过河 (0, 2),一名贩子过河 (1, 0),一名仆役过河 (0, 1)。
基于当前船地点的位置,贩子和仆役要么从左岸到右岸(如果船在左岸),要么从右岸到左岸(如果船在右岸)。
合法状态条件:
如果左岸有贩子和仆役,必须满足左岸的贩子数 >= 左岸的仆役数。
如果右岸有贩子和仆役,也必须满足右岸的贩子数 >= 右岸的仆役数。
如果某岸没有贩子,则无需思量仆役数目。
目标函数

题目标目标是找到一种安全的过河战略,使得全部贩子和仆役安全过河,而且最少步数完成过河过程。步数是须要最小化的目标函数。
束缚条件


  •         每次船的载重不能高出两人。
  •         每次过河之后,任何一岸的仆役数不能高出贩子数。
  •         贩子决定搭船方案,仆役不能独立决定过河。
BFS求解

广度优先搜刮(BFS)是一种常用来探求最短路径的算法,恰当用来办理这种题目。
详细步调如下:

  •         从初始状态 (3, 3, 1) 开始,参加队列。
  •         对于队列中的每个状态,实验全部大概的合法过河方式,天生新状态。
  •         如果新状态满足安全条件而且没有被访问过,将其参加队列。
  •         当某个状态到达目标状态 (0, 0, 0) 时,制止搜刮,返回路径。
  •         如果全部状态都搜刮完毕还没有找到解,则分析题目无解。
  1. from collections import deque
  2. ​
  3. # 定义初始状态 (左岸商人数量, 左岸仆人数量, 船所在岸 1表示左岸, 0表示右岸)
  4. initial_state = (3, 3, 1)
  5. goal_state = (0, 0, 0)
  6. ​
  7. # 检查状态是否合法
  8. def is_valid(state):
  9.    left_m, left_s, _ = state
  10.    right_m = 3 - left_m
  11.    right_s = 3 - left_s
  12.    # 检查两岸的商人数和仆人数比例
  13.    if (left_m >= 0 and left_s >= 0 and left_m >= left_s) or left_m == 0:
  14.        if (right_m >= 0 and right_s >= 0 and right_m >= right_s) or right_m == 0:
  15.            return True
  16.    return False
  17. ​
  18. # 使用BFS算法来搜索最优解
  19. def bfs():
  20.    queue = deque([(initial_state, [])])  # 队列保存当前状态和走过的路径
  21.    visited = set()  # 记录已经访问过的状态
  22.    visited.add(initial_state)
  23.    
  24.    while queue:
  25.        current_state, path = queue.popleft()
  26.        
  27.        # 如果到达目标状态,返回路径
  28.        if current_state[:2] == goal_state[:2] and current_state[2] == goal_state[2]:
  29.            return path + [current_state]
  30.        
  31.        left_m, left_s, boat = current_state
  32.        new_boat = 1 - boat  # 切换船所在的岸
  33.        
  34.        # 定义所有可能的船的移动情况
  35.        moves = [
  36.            (1, 0), (0, 1), (1, 1), (2, 0), (0, 2)  # (商人移动数量, 仆人移动数量)
  37.        ]
  38.        
  39.        for move_m, move_s in moves:
  40.            if boat == 1:  # 如果船在左岸
  41.                new_state = (left_m - move_m, left_s - move_s, new_boat)
  42.            else:  # 如果船在右岸
  43.                new_state = (left_m + move_m, left_s + move_s, new_boat)
  44.            
  45.            # 检查新状态是否合法
  46.            if is_valid(new_state) and new_state not in visited:
  47.                visited.add(new_state)
  48.                queue.append((new_state, path + [current_state]))
  49. ​
  50.    return None
  51. ​
  52. # 运行BFS算法
  53. result = bfs()
  54. ​
  55. if result:
  56.    print("找到安全过河方案,最少步骤为:", len(result) - 1)
  57.    for step in result:
  58.        print(step)
  59. else:
  60.    print("没有找到安全过河方案。")
复制代码
求解效果
  1. 找到安全过河方案,最少步骤为: 11
  2. (3, 3, 1)
  3. (2, 2, 0)
  4. (3, 2, 1)
  5. (3, 0, 0)
  6. (3, 1, 1)
  7. (1, 1, 0)
  8. (2, 2, 1)
  9. (0, 2, 0)
  10. (0, 3, 1)
  11. (0, 1, 0)
  12. (1, 1, 1)
  13. (0, 0, 0)
复制代码
得到方案如下:
贩子和仆役最少颠末11步安全渡河。起首,一名贩子和一名仆役过河,两岸各有2名贩子和2名仆役。接着,一名仆役回到左岸,左岸有3名贩子和2名仆役。然后,两名仆役过河,左岸剩下3名贩子,右岸有3名仆役和2名贩子。接着一名仆役返回左岸,左岸有3名贩子和1名仆役。随后,两名贩子过河,左岸剩下1名贩子和1名仆役。接着一名贩子和一名仆役返回,左右岸再次各有2名贩子和2名仆役。然后两名贩子过河,左岸只剩下仆役,右岸有4名贩子和2名仆役。接着一名仆役回到左岸,左岸有1名仆役,右岸有4名贩子和1名仆役。随后两名仆役过河,右岸全部人到达。末了,一名仆役回到左岸,并带着末了的贩子和仆役安全到达右岸,完玉成部渡河过程。
题目C

四个著名的音乐人受邀成为一场音乐角逐的评委,评委席的座次安排一他们相互忍让,末了组委会不得不让他们投票选出本身心中的座次安排,如果你是组委会拿到了如下的投票效果,叨教你将怎样安排座次?(注:排在最前面的坐首席)
甲:乙丙丁甲
乙:丙甲丁乙
丙:甲丙丁乙
丁:甲丙乙丁
解:根据每个人的投票序次,为每个评委举行排序打分。排名越靠前,得分越高。假设排名第一得 3 分,排名第二得 2 分,排名第三得 1 分,排名第四得 0 分;然后将全部投票效果举行加总,得出每位评委的总分,分数高者安排在靠前的位置。
编写代码如下:
  1. # 定义每位评委的投票顺序
  2. votes = {
  3.    '甲': ['乙', '丙', '丁', '甲'],
  4.    '乙': ['丙', '甲', '丁', '乙'],
  5.    '丙': ['甲', '丙', '丁', '乙'],
  6.    '丁': ['甲', '丙', '乙', '丁']
  7. }
  8. # 初始化得分表
  9. scores = {'甲': 0, '乙': 0, '丙': 0, '丁': 0}
  10. # 给每个评委根据投票顺序打分
  11. for voter, ranking in votes.items():
  12.    # 第一名得3分,第二名得2分,第三名得1分,第四名得0分
  13.    for i, candidate in enumerate(ranking):
  14.        scores[candidate] += 3 - i
  15. # 按得分从高到低排序
  16. sorted_scores = sorted(scores.items(), key=lambda x: x[1], reverse=True)
  17. # 输出最终座次安排
  18. print("最终座次安排:")
  19. for i, (name, score) in enumerate(sorted_scores, 1):
  20.    print(f"第{i}名: {name},得分: {score}")
复制代码
求得效果:
  1. 最终座次安排:
  2. 第1名: 丙,得分: 9
  3. 第2名: 甲,得分: 8
  4. 第3名: 乙,得分: 4
  5. 第4名: 丁,得分: 3
复制代码
故应将座位安排为丙甲乙丁。

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表