2024第五届华数杯数学建模竞赛C题思路+代码

目录

原题背景

最近,"city 不 city"这一网络流行语在外国网红的推动下备受关注。随着我国过境免签政策的落实,越来越多外国游客来到中国,通过网络平台展示他们在华旅行的见闻,这不仅推动了中国旅游业的发展,更是在国际舞台上展现了一个 真实而生动的中国,一举多得。

假设外国游客入境后能在中国境内逗留 144 小时,且能从任一城市附近的机场出境。由于每个城市景点较多,为了便于外国游客能够游览到更多的城市,现假定"每个城市只选择一个评分最高的景点游玩",称之为"城市最佳景点游览原 则"。

现有一个包含中国(不含港澳台)352 个城市的旅游景点的数据集,每个城 市的 csv 文件中有 100

个景点,每个景点的信息包含有景点名称、网址、地址、 景点介绍、开放时间、图片网址、景点评分、建议游玩时长、建议游玩季节、门票信息、小贴士等。

背景分析

提取关键信息

(1)"城市最佳景点游览原则" :假设外国游客入境后能在中国境内逗留 144 小时,且能从任一城市附近的机场出境。由于每个城市景点较多,为了便于外国游客能够游览到更多的城市,现假定"每个城市只选择一个评分最高的景点游玩",称之为"城市最佳景点游览原则"。

(2)数据说明 :现有一个包含中国(不含港澳台)352 个城市的旅游景点的数据集,每个城 市的 csv 文件中有 100个景点,每个景点的信息包含有景点名称、网址、地址、 景点介绍、开放时间、图片网址、景点评分、建议游玩时长、建议游玩季节、门票信息、小贴士等。
分析题目背景

本题为了帮助外国游客在有限的时间内游览中国的最佳景点,我们需要利用数据集中的信息进行一些分析和建模。

  • 首先根据关键信息(1),我们需要从每个城市的数据集中提取评分最高的景点信息。假设我们已经有了包含352个城市旅游景点的CSV文件。对每个城市,找到评分最高的景点,并记录其信息。我们可以编写一个脚本来处理这些CSV文件,并提取所需的数据。
  • 其次,考虑到游客在144小时内需要游览多个城市,并且可能需要在不同城市之间进行交通转换,我们可以使用以下几种数学模型进行优化:
    • 旅行商问题 (TSP):
        这个问题可以被看作是一个典型的旅行商问题,其中每个城市是一个节点,景点是游客需要访问的地方。目标是找到一个路径,使得总的旅行时间或距离最小,同时确保游客在每个城市的停留时间在合理范围内。
    • 时变网络模型:
        考虑到不同交通方式(如高铁、飞机)的时间和费用,我们可以构建一个时变网络模型来优化旅行路径和时间。

下面,我们将根据具体的问题进行分析和解答。

问题一

原题

请问 352 个城市中所有 35200 个景点评分的最高分(Best Score,简称 BS)是多少?全国有多少个景点获评了这个最高评分(BS)?获评了这个最高评分(BS)景点最多的城市有哪些?依据拥有最高评分(BS)景点数量的多少排序,列出前 10 个城市。

思路

Step1:数据读取与处理

首先,我们需要读取所有352个城市的CSV文件,并提取每个景点的评分数据。我们可以使用Python中的Pandas库来处理这些数据。

其次,因为数据中存在数据缺失和类型不匹配问题,我们需要将空值剔除或者用0来填补,并将str型数据转换成float型。

Step2:计算最高评分(Best Score, BS)

我们需要遍历所有景点的评分数据,找到最高评分(BS)。然后统计获得最高评分(BS)的景点数量以及这些景点所在的城市。

Step3:统计各城市的最高评分(BS)景点数量

我们需要统计每个城市中获得最高评分(BS)的景点数量,并按数量排序,列出前10个城市。

程序

读取数据

python 复制代码
import pandas as pd
import os

# 假设所有城市的CSV文件都存储在 "cities_data" 目录下
directory = "./附件"

# 用于存储所有景点评分数据
all_sights = []

# 遍历每个城市的CSV文件
for filename in os.listdir(directory):
    if filename.endswith(".csv"):
        city = filename.split('.')[0]
        df = pd.read_csv(os.path.join(directory, filename))
        df['城市'] = city
        all_sights.append(df)

# 合并所有城市的数据
all_sights_df = pd.concat(all_sights)

all_sights_df

数据预处理

处理空值,将空值替换为数字0

将数据中的评分列转为数值型

python 复制代码
# ValueError: could not convert string to float: '--
all_sights_df['评分'] = pd.to_numeric(all_sights_df['评分'], errors='coerce')
# Convert '评分' column from object to float
all_sights_df['评分'] = all_sights_df['评分'].astype(float)

寻找最终答案并输出结果:

python 复制代码
# 找到最高评分(BS)
best_score = all_sights_df['评分'].max()

# 统计获得最高评分(BS)的景点数量
best_sights = all_sights_df[all_sights_df['评分'] == best_score]
best_sights_count = best_sights.shape[0]

# 统计每个城市中获得最高评分(BS)的景点数量
city_best_sights_count = best_sights['城市'].value_counts()

# 找到拥有最高评分(BS)景点数量最多的前10个城市
top_10_cities = city_best_sights_count.head(10)

# 输出结果
print(f"最高评分(BS)为:{best_score}")
print(f"全国共有 {best_sights_count} 个景点获得最高评分(BS)")
print("拥有最高评分(BS)景点最多的前10个城市为:")
print(top_10_cities)

问题二

原题

假如外国游客遵循"城市最佳景点游览原则",结合城市规模、环境环保、人文底蕴、交通便利,以及气候、美食等因素,请你对 352 个城市进行综合评价,选出"最令外国游客向往的 50 个城市"。

思路

要对352个城市进行综合评价,选出"最令外国游客向往的50个城市",我们需要建立一个多因素评价模型。这些因素包括城市规模、环境环保、人文底蕴、交通便利、气候、美食等。我们可以通过加权评分的方法来综合评估这些城市。

Step1: 定义评价指标

  • 城市规模:可以用城市人口或GDP来衡量。
  • 环境环保:可以用PM2.5平均浓度或城市绿化率来衡量。
  • 人文底蕴:可以用历史遗迹数量、博物馆数量等来衡量。
  • 交通便利:可以用公共交通覆盖率、交通便捷性等来衡量。
  • 气候:可以用气候舒适度指数来衡量。
  • 美食:可以用美食评价、餐厅数量等来衡量。

Step2: 收集数据

假设我们已经收集了上述指标的数据,可以用一个CSV文件来表示,其中每一列代表一个城市,每一列代表一个评价指标。

因为在原始的数据文件中指包含地点名称、网址、地址、景点介绍、开放时间、图片网址、评分、建议游玩时长、建议游玩季节、门票信息、小贴士等。并没有题目中的城市规模、环境保护、人文底蕴等信息,所以这部分数据需要我们自己补充。

Step3: 标准化数据

由于各个指标的量纲不同,需要对数据进行标准化处理。

Step4: 加权评分

给每个指标分配权重,根据加权评分计算每个城市的综合评分。

Step5: 选出前50个城市

根据综合评分进行排序,选出前50个城市。

程序

python 复制代码
import pandas as pd
from sklearn.preprocessing import MinMaxScaler

# 假设已经有一个包含所有城市及其各个评价指标的CSV文件
data = pd.read_csv('city_evaluation_data.csv')

# 定义各个评价指标的权重
weights = {
    '城市规模': 0.2,
    '环境环保': 0.2,
    '人文底蕴': 0.2,
    '交通便利': 0.2,
    '气候': 0.1,
    '美食': 0.1
}

# 对数据进行标准化处理
scaler = MinMaxScaler()
normalized_data = pd.DataFrame(scaler.fit_transform(data[list(weights.keys())]), columns=list(weights.keys()))

# 计算综合评分
normalized_data['综合评分'] = 0
for key in weights.keys():
    normalized_data['综合评分'] += normalized_data[key] * weights[key]

# 将综合评分添加回原始数据
data['综合评分'] = normalized_data['综合评分']

# 根据综合评分进行排序,选出前50个城市
top_50_cities = data.sort_values(by='综合评分', ascending=False).head(50)

import ace_tools as tools; tools.display_dataframe_to_user(name="Top 50 Cities for Foreign Tourists", dataframe=top_50_cities)

# 输出结果
print("最令外国游客向往的前50个城市为:")
print(top_50_cities[['城市', '综合评分']])

问题三

原题

现有一名外国游客从广州入境,他想在 144 小时以内游玩尽可能多的城市,同时要求综合游玩体验最好,请你规划他的游玩路线。需要结合游客的要求给出具体的游玩路线,包括总花费时间,门票和交通的总费用以及可以游玩的景点数量。他的要求有:

  • ① 遵循城市最佳景点游览原则;
  • ② 城市之间的交通方式只选择高铁;
  • ③ 只在"最令外国游客向往的 50 个城市"中选择要游玩的城市。

思路

为了解决这个问题,我们需要建立一个优化模型,该模型考虑了游客的需求、时间限制以及交通方式。以下是具体步骤:

Step1: 数据准备

  • 城市数据:包括"最令外国游客向往的50个城市"以及每个城市的最佳景点。
  • 高铁交通数据:包括城市之间的高铁行程时间和费用。
  • 景点数据:包括每个城市最佳景点的门票费用和游玩时间。

Step2: 优化目标

我们的目标是在144小时内最大化游客能够游玩的城市数量,同时保证综合游玩体验最佳。这可以通过以下步骤实现:

  • 定义时间约束:包括每个城市的游玩时间和城市之间的交通时间,确保总时间不超过144小时。
  • 综合评分:根据前面定义的综合评分标准,确保选择的城市能够提供最佳的游玩体验。
  • 费用计算:计算总花费,包括门票费用和高铁交通费用。

Step3: 建立模型

我们可以使用整数规划(Integer Programming)来解决这个优化问题。

为了建立问题3的模型,我们需要优化外国游客在144小时内游览尽可能多的城市,同时使综合游玩体验最好。这个问题可以通过整数规划(Integer Programming)来解决。以下是模型的详细步骤、公式和Python代码实现。

  1. 数据准备

    • 从数据集中读取"最令外国游客向往的50个城市"及其最佳景点的信息。
    • 获取城市之间的高铁交通时间和费用。
  2. 定义决策变量

    • x i x_i xi:表示是否选择城市 i i i(1 表示选择,0 表示不选择)。
  3. 定义约束条件

    • 总游玩时间不超过144小时。
  4. 定义目标函数

    • 最大化游客可以游览的城市数量,同时综合考虑游玩体验。

模型公式:

  1. 决策变量

    • x i x_i xi:城市 i i i 是否被选择游览, x i ∈ { 0 , 1 } x_i \in \{0, 1\} xi∈{0,1}。
  2. 约束条件

    • 总游玩时间不超过144小时:
      ∑ i = 1 n ( t t r a v e l , i + t s i g h t , i ) ⋅ x i ≤ 144 \sum_{i=1}^{n} (t_{travel, i} + t_{sight, i}) \cdot x_i \leq 144 i=1∑n(ttravel,i+tsight,i)⋅xi≤144
      其中 t t r a v e l , i t_{travel, i} ttravel,i 是从当前城市到城市 i i i 的旅行时间, t s i g h t , i t_{sight, i} tsight,i 是城市 i i i 的游玩时间。
  3. 目标函数

    • 最大化游览城市数量,并考虑游玩体验评分:
      Maximize ∑ i = 1 n ( s i ⋅ x i ) \text{Maximize} \quad \sum_{i=1}^{n} (s_i \cdot x_i) Maximizei=1∑n(si⋅xi)
      其中 s i s_i si 是城市 i i i 的综合评分。

参考代码

python 复制代码
import pandas as pd
from ortools.linear_solver import pywraplp

# 读取数据
top_50_cities = pd.read_csv('top_50_cities.csv')  # 包含最令外国游客向往的50个城市及其综合评分
high_speed_rail = pd.read_csv('high_speed_rail.csv')  # 包含城市之间的高铁交通时间和费用
city_best_sights = pd.read_csv('city_best_sights.csv')  # 包含每个城市最佳景点的游玩时间和门票费用

# 初始化模型
solver = pywraplp.Solver.CreateSolver('SCIP')

# 定义变量
cities = top_50_cities['城市'].tolist()
n = len(cities)
x = {}
for i in range(n):
    x[i] = solver.IntVar(0, 1, f'x[{i}]')

# 时间和费用数据
travel_time = high_speed_rail.set_index('目的地')['时间'].to_dict()
sight_time = city_best_sights.set_index('城市')['建议游玩时长'].to_dict()
sight_cost = city_best_sights.set_index('城市')['门票费用'].to_dict()
city_score = top_50_cities.set_index('城市')['综合评分'].to_dict()

# 定义约束条件:时间限制
time_limit = 144  # 小时
time_constraints = solver.Constraint(0, time_limit)
for i in range(n):
    city = cities[i]
    time_constraints.SetCoefficient(x[i], travel_time.get(city, 0) + sight_time.get(city, 0))

# 定义目标函数:最大化综合游玩体验(评分)
objective = solver.Objective()
for i in range(n):
    city = cities[i]
    objective.SetCoefficient(x[i], city_score[city])
objective.SetMaximization()

# 求解模型
status = solver.Solve()

if status == pywraplp.Solver.OPTIMAL:
    total_time = 0
    total_cost = 0
    total_sights = 0
    visited_cities = []

    for i in range(n):
        if x[i].solution_value() == 1:
            city = cities[i]
            total_time += travel_time.get(city, 0) + sight_time.get(city, 0)
            total_cost += sight_cost.get(city, 0)
            total_sights += 1
            visited_cities.append(city)
    
    print("总游玩时间:", total_time, "小时")
    print("总费用:", total_cost, "元")
    print("总游玩景点数量:", total_sights, "个")
    print("游玩城市列表:", visited_cities)
else:
    print("No optimal solution found.")

# 显示数据框
import ace_tools as tools; tools.display_dataframe_to_user(name="Top 50 Cities for Foreign Tourists", dataframe=top_50_cities)

问题四

原题

如果将问题 3 的游览目标改为:既要尽可能的游览更多的城市,又需要使门票和交通的总费用尽可能的少。请重新规划游玩路线,并给出门票和交通的总费用,总花费时间以及可以游玩的城市数量。

思路

Step1:数据准备

假设我们仍然有相同的数据集,包括"最令外国游客向往的50个城市"及其相关信息。

Step2: 优化目标

  • 最大化游玩城市数量:通过整数规划来选择尽可能多的城市。
  • 最小化费用:在第一个目标的基础上,最小化门票和交通的总费用。

Step3: 建立模型

  1. 数据准备

    • 从数据集中读取"最令外国游客向往的50个城市"及其最佳景点的信息。
    • 获取城市之间的高铁交通时间和费用。
  2. 定义决策变量

    • x i x_i xi:表示是否选择城市 i i i(1 表示选择,0 表示不选择)。
  3. 定义约束条件

    • 总游玩时间不超过144小时。
  4. 定义目标函数

    • 在144小时内,最大化游览城市数量,并最小化总费用。

模型公式

  1. 决策变量

    • x i x_i xi:城市 i i i是否被选择游览, x i ∈ { 0 , 1 } x_i \in \{0, 1\} xi∈{0,1}。
  2. 约束条件

    • 总游玩时间不超过144小时:
      ∑ i = 1 n ( t t r a v e l , i + t s i g h t , i ) ⋅ x i ≤ 144 \sum_{i=1}^{n} (t_{travel, i} + t_{sight, i}) \cdot x_i \leq 144 i=1∑n(ttravel,i+tsight,i)⋅xi≤144
  3. 目标函数

    • 最大化游览城市数量,并最小化费用:
      Maximize ∑ i = 1 n x i − λ ( ∑ i = 1 n ( c t r a v e l , i + c s i g h t , i ) ⋅ x i ) \text{Maximize} \quad \sum_{i=1}^{n} x_i - \lambda \left( \sum_{i=1}^{n} (c_{travel, i} + c_{sight, i}) \cdot x_i \right) Maximizei=1∑nxi−λ(i=1∑n(ctravel,i+csight,i)⋅xi)
      其中:
    • λ \lambda λ 是一个调整参数,用于平衡游览数量和费用之间的权重。
    • c t r a v e l , i c_{travel, i} ctravel,i 是城市 i i i 的交通费用。
    • c s i g h t , i c_{sight, i} csight,i 是城市 i i i 的门票费用。

参考代码

python 复制代码
import pandas as pd
from ortools.linear_solver import pywraplp

# 读取数据
top_50_cities = pd.read_csv('top_50_cities.csv')  # 包含最令外国游客向往的50个城市及其综合评分
high_speed_rail = pd.read_csv('high_speed_rail.csv')  # 包含城市之间的高铁交通时间和费用
city_best_sights = pd.read_csv('city_best_sights.csv')  # 包含每个城市最佳景点的游玩时间和门票费用

# 初始化模型
solver = pywraplp.Solver.CreateSolver('SCIP')

# 定义变量
cities = top_50_cities['城市'].tolist()
n = len(cities)
x = {}
for i in range(n):
    x[i] = solver.IntVar(0, 1, f'x[{i}]')

# 时间和费用数据
travel_time = high_speed_rail.set_index('目的地')['时间'].to_dict()
travel_cost = high_speed_rail.set_index('目的地')['费用'].to_dict()
sight_time = city_best_sights.set_index('城市')['建议游玩时长'].to_dict()
sight_cost = city_best_sights.set_index('城市')['门票费用'].to_dict()

# 定义约束条件:时间限制
time_limit = 144  # 小时
time_constraints = solver.Constraint(0, time_limit)
for i in range(n):
    city = cities[i]
    time_constraints.SetCoefficient(x[i], travel_time.get(city, 0) + sight_time.get(city, 0))

# 定义目标函数:最大化游览城市数量,并最小化费用
# 这里我们使用一个权重参数 lambda 来平衡两者
lambda_weight = 0.01
objective = solver.Objective()
for i in range(n):
    objective.SetCoefficient(x[i], 1 - lambda_weight * (travel_cost.get(cities[i], 0) + sight_cost.get(cities[i], 0)))
objective.SetMaximization()

# 求解模型
status = solver.Solve()

if status == pywraplp.Solver.OPTIMAL:
    total_time = 0
    total_cost = 0
    total_sights = 0
    visited_cities = []

    for i in range(n):
        if x[i].solution_value() == 1:
            city = cities[i]
            total_time += travel_time.get(city, 0) + sight_time.get(city, 0)
            total_cost += travel_cost.get(city, 0) + sight_cost.get(city, 0)
            total_sights += 1
            visited_cities.append(city)
    
    print("总游玩时间:", total_time, "小时")
    print("总费用:", total_cost, "元")
    print("总游玩景点数量:", total_sights, "个")
    print("游玩城市列表:", visited_cities)
else:
    print("No optimal solution found.")

# 显示数据框
import ace_tools as tools; tools.display_dataframe_to_user(name="Top 50 Cities for Foreign Tourists", dataframe=top_50_cities)

问题五

原题

现有一名外国游客只想游览中国的山景,他乘飞机入境中国的城市不限。请你为他选择入境的机场和城市,并个性化定制他的 144 小时旅游路线,既要尽可能的游览更多的山,又需要使门票和交通的总费用尽可能的少。需要结合游客的要求给出具体的游玩路线,包括总花费时间,门票和交通的总费用以及可以游玩的景点数量。他的要求有:

  • ① 每个城市只游玩一座评分最高的山;
  • ② 城市之间的交通方式只选择高铁;
  • ③ 旅游城市不局限于"最令外国游客向往的 50 个城市",游览范围拓展到
    352 个城市。

思路

为了帮助这名外国游客在144小时内游览尽可能多的山景,并且在控制费用的情况下选择最佳路线,我们需要建立一个多目标优化模型。以下是具体步骤:

Step1: 数据准备

  • 城市和山景数据:包括352个城市及其评分最高的山景、游玩时间、门票费用等信息。
  • 高铁交通数据:包括城市之间的高铁行程时间和费用。
  • 机场数据:包括352个城市中主要机场的位置和信息。

Step2: 优化目标

  • 最大化游览山景数量:尽可能多地游览不同城市的评分最高的山景。
  • 最小化费用:在游览尽可能多山景的基础上,最小化总的门票和交通费用。

Step3: 选择入境城市

选择入境城市的策略可以基于入境城市到其他城市的高铁交通便利性和山景的分布情况。

Step4: 建立模型

我们同样可以使用整数规划(Integer Programming)来解决这个优化问题。

更详细具体的视频讲解(更新)

具体见我B站视频:B站

程序

如果需要更多详细代码,请把上述思路复制粘贴到我的gpt网站生成代码 传送门

相关推荐
煤泥做不到的!1 小时前
挑战一个月基本掌握C++(第十一天)进阶文件,异常处理,动态内存
开发语言·c++
F-2H1 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
bryant_meng2 小时前
【python】OpenCV—Image Moments
开发语言·python·opencv·moments·图片矩
若亦_Royi3 小时前
C++ 的大括号的用法合集
开发语言·c++
资源补给站4 小时前
大恒相机开发(2)—Python软触发调用采集图像
开发语言·python·数码相机
m0_748247554 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
6.944 小时前
Scala学习记录 递归调用 练习
开发语言·学习·scala
FF在路上4 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
余额不足121385 小时前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
众拾达人5 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言