当前位置: 首页 > article >正文

练7:模拟

欢迎大家订阅【蓝桥杯Python每日一练】 专栏,开启你的 Python数据结构与算法 学习之旅!

文章目录

  • 1 模拟
  • 2 例题详解
    • 2.1 饮料换购
    • 2.2 图像模糊
    • 2.3 螺旋矩阵


1 模拟

①定义
模拟(Simulation)是计算机科学中的一种常见问题解决方法,指的是通过构造模型和模拟真实世界中的过程、现象或系统,来实现问题的解决。

在编程中,模拟通常涉及按照题目的描述,逐步模拟某一过程或状态的变化,并最终得出所需的结果。

②特点

  • 根据规则逐步执行: 模拟问题的关键在于按照给定的规则或流程,逐步模拟某一事件的发生或系统的状态变化。每一步都要根据当前的状态决定下一步的操作。
  • 状态变化: 模拟题通常要求追踪和管理系统中的状态。在模拟过程中,每次操作都会对系统的状态进行更新,直到达到最终目标或满足终止条件。
  • 顺序操作: 模拟问题通常要求按照一定的顺序进行操作,按照题目要求的流程(如输入、处理、输出),并且每个操作都与前后的状态紧密关联。
  • 简单规则的迭代实现: 虽然模拟题的规则可能较为简单,但需要通过多次迭代来完成任务。常见的操作如循环、状态更新、边界检查等。
  • 避免复杂的数学计算或高深的算法: 模拟题不一定需要高级的数学知识或复杂的算法,更侧重于如何按步骤实现任务和维护状态。

③解题技巧
在这里插入图片描述

2 例题详解

2.1 饮料换购

在这里插入图片描述
题目地址:https://www.lanqiao.cn/problems/143/learning/

样例输入

100

样例输出

149

【题目分析】
①模拟思路: 题目要求模拟通过饮料瓶盖换购饮料的过程,每次以固定规则更新瓶盖和饮料总数,直到不满足换购条件。

②模拟特性:
直接按题意执行:

  • 每次用 3 个瓶盖换 1 瓶饮料。
  • 换购后更新剩余瓶盖数量。
  • 循环结束条件为瓶盖数量不足 3。

模拟过程中需要追踪状态变化(当前瓶盖数量、已换购饮料总数)。
本题直接实现规则和状态更新,无需复杂算法,是典型的模拟问题。

代码示例
【示例1】

# n表示瓶盖的数量
n=int(input())
ans=n

# 法1
while True:
    if n>=3:
        # 把三个瓶盖换成一个饮料
        n-=3
        # 统计饮料的总和
        ans+=1
        # 更新瓶盖数量
        n+=1
    else:
        break

print(ans)

【示例2】

# n表示瓶盖的数量
n=int(input())
ans=n
# 法2
while True:
    if n>=3:
        # n个瓶盖可以换n//3瓶饮料,还剩下n%3个瓶盖
        # 统计饮料的总和
        ans+=n//3
        # 更新瓶盖数量
        n+=1n//3+n%3
    else:
        break
print(ans)

运行结果
在这里插入图片描述

2.2 图像模糊

在这里插入图片描述
题目地址:https://www.lanqiao.cn/problems/550/learning/

样例输入

3 4
0 0 0 255
0 0 255 0
0 30 255 255

样例输出

0 42 85 127
5 60 116 170
7 90 132 191

【题目分析】
①模拟思路: 题目要求对矩阵中的每个元素,计算它与周围的元素的平均值,并将结果存入新的矩阵中。通过遍历矩阵并逐步计算每个位置的模糊值来完成任务。

②模拟特性

a. 逐步按题意处理每个像素点:

  • 确定当前像素的周围邻居范围。
  • 累加有效邻居的值并计算平均。
  • 更新模糊矩阵中的对应位置。

b. 符合模拟问题的两个关键特点:

  • 状态更新:每个像素点的模糊值基于周围像素的状态计算。
  • 逐步实现:直接模拟矩阵模糊的计算过程。

代码示例

n,m=map(int,input().split())
Map=[]
for i in range(n):
    a=list(map(int,input().split()))
    Map.append(a)

# 构建一个n行m列的二维list
ans=[[0]*m for i in range(n)]

for i in range(n):
    for j in range(m):
        # 遍历每个位置,求出模糊后的结果
        # (i-1,j-1)  (i-1,j)  (i-1,j+1)
        # (i,j-1)    (i,j)    (i,j+1)
        # (i+1,j-1)  (i+1,j)  (i+1,j+1)

        # 分别表示总和及个数
        tot,cnt=0,0
        # 遍历周围3*3区域
        for delta_x in [-1,0,1]:
            for delta_y in [-1,0,1]:
                x=i+delta_x
                y=j+delta_y
                # 判断坐标(x,y)是否存在
                if 0<=x<n and 0<=y<m:
                    tot+=Map[x][y]
                    cnt+=1

        ans[i][j]=tot//cnt

for a in ans:
    print(' '.join(map(str,a)))
                    

【代码分析】

①输入数据

n, m = map(int, input().split())

这行代码读取矩阵的行数 n 和列数 m,根据样例输入:

3 4

此时:

  • n = 3 (矩阵有 3 行)
  • m = 4 (矩阵有 4 列)

②读取矩阵数据

Map = []
for i in range(n):
    a = list(map(int, input().split()))
    Map.append(a)
  • 循环 n 次,每次读取一行的数字并存储到 Map 中。
  • 样例输入的数据分别是:
    0 0 0 255
    0 0 255 0
    0 30 255 255
    

最终矩阵 Map 存储为一个二维列表:

Map = [
    [0, 0, 0, 255],
    [0, 0, 255, 0],
    [0, 30, 255, 255]
]

③构建结果矩阵

ans = [[0] * m for _ in range(n)]
  • 初始化一个大小为 n × m 的二维列表 ans,所有元素都为 0,用来存储模糊后的结果。
  • 初始状态为:
ans = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
]

④模糊处理

外层双循环:

for i in range(n):      # 遍历矩阵的每一行
    for j in range(m):  # 遍历矩阵的每一列

这里 (i, j) 是当前正在处理的矩阵位置。

⑤计算模糊值
对于位置 (i, j),计算其周围 3×3 区域的模糊值。

【遍历 3×3 区域】

for delta_x in [-1, 0, 1]:         # 遍历相对于 i 的偏移
    for delta_y in [-1, 0, 1]:     # 遍历相对于 j 的偏移

(delta_x, delta_y) 是偏移量,表示当前位置 (i, j) 的邻居:

  • delta_x = -1 表示上方一行
  • delta_x = 0 表示当前行
  • delta_x = 1 表示下方一行

【计算邻居位置】

x = i + delta_x      # 计算邻居的行索引
y = j + delta_y      # 计算邻居的列索引

【检查边界合法性】

if 0 <= x < n and 0 <= y < m:

检查 (x, y) 是否在矩阵范围内:

  • 行号 x 必须在 [0, n-1] 范围内。
  • 列号 y 必须在 [0, m-1] 范围内。
  • 如果邻居超出矩阵范围,则忽略。

⑥累加值和计数
对于合法的 (x, y)

tot += Map[x][y]      # 累加邻居的值
cnt += 1              # 统计有效邻居的数量
  • tot 是邻居元素的总和,cnt 是有效邻居的数量。

⑦平均值计算
计算模糊后的值并存入结果矩阵:

ans[i][j] = tot // cnt

tot // cnt 是总和除以有效数量,取整。


⑧输出结果

for a in ans:
    print(' '.join(map(str, a)))
  • 遍历 ans 矩阵的每一行,将其转换为字符串并打印。

运行结果
在这里插入图片描述

2.3 螺旋矩阵

在这里插入图片描述

题目地址:https://www.lanqiao.cn/problems/156/learning/

样例输入

4 5
2 2

样例输出

15

【题目分析】
①模拟思路::按照螺旋顺序填充矩阵,逐步将值填入每个位置,最终输出目标位置的值。

②模拟特性:
a. 按题意执行:

  • 从左上角开始,按右、下、左、上的方向依次填充矩阵。
  • 边界条件控制填充的范围。

b. 需要状态维护:

  • 当前填充值。
  • 当前方向(右、下、左、上)的变化规则。
  • 已填充的位置状态避免重复覆盖。

c. 模拟问题的核心是动态更新矩阵状态和循环实现填充过程。

代码示例

n,m=map(int,input().split())
r,c=map(int,input().split())

# 初始化矩阵
ans=[[0]*m for i in range(n)]

# 当前坐标
x,y=0,0

# 当前存放的值
value=1
ans[x][y]=value

# 填充螺旋矩阵
while value<n*m:
    # 往右走(x,y+1)
    while y+1<m and ans[x][y+1]==0:
        value+=1
        y+=1
        ans[x][y]=value

     # 往下走(x+1,y)
    while x+1<n and ans[x+1][y]==0:
         value+=1
         x+=1
         ans[x][y]=value

     # 往左走(x,y-1)
    while y-1>=0 and ans[x][y-1]==0:
         value+=1
         y-=1
         ans[x][y]=value

      # 往上走(x-1,y)
    while x-1>=0 and ans[x-1][y]==0:
         value+=1
         x-=1
         ans[x][y]=value

# 输出目标位置的值
print(ans[r-1][c-1]) 
        

【代码分析】

①输入部分

n, m = map(int, input().split())  # 矩阵大小,n 行 m 列
r, c = map(int, input().split())  # 目标位置 (r, c)
  • 示例输入:4 5 表示矩阵大小为 ( 4 * 5 )。
  • 示例输入:2 2 表示目标位置为矩阵第 2 行第 2 列。

②初始化矩阵

ans = [[0] * m for i in range(n)]  # 创建一个 n 行 m 列的矩阵,初始值为 0

构造一个 ( 4 * 5 ) 的矩阵:

 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0

③设置初始位置和填充值

x, y = 0, 0  # 初始位置在左上角
value = 1    # 初始值为 1
ans[x][y] = value

设置矩阵左上角 ((0,0)) 为 1:

 1  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0

④填充矩阵(螺旋过程)

  • 主循环:当 value < n * m 时继续填充。
  • 方向顺序:右 → 下 → 左 → 上。

a. 往右填充:

while y + 1 < m and ans[x][y + 1] == 0:
    value += 1
    y += 1
    ans[x][y] = value
  • 持续向右填充,直到无法前进(列超出范围或右侧已填充)。
  • y 从 0 -> 4,对应矩阵:
    1  2  3  4  5
    0  0  0  0  0
    0  0  0  0  0
    0  0  0  0  0
    

2. 往下填充:

while x + 1 < n and ans[x + 1][y] == 0:
    value += 1
    x += 1
    ans[x][y] = value
  • 持续向下填充,直到无法前进。
  • x 从 0 -> 3,对应矩阵:
1  2  3  4  5
0  0  0  0  6
0  0  0  0  7
0  0  0  0  8

c. 往左填充:

while y - 1 >= 0 and ans[x][y - 1] == 0:
    value += 1
    y -= 1
    ans[x][y] = value
  • 持续向左填充,直到无法前进。
  • y 从 4 -> 0,对应矩阵:
1  2  3  4  5
0  0  0  0  6
0  0  0  0  7
12 11 10  9  8

d. 往上填充:

while x - 1 >= 0 and ans[x - 1][y] == 0:
    value += 1
    x -= 1
    ans[x][y] = value
  • 持续向上填充,直到无法前进。
  • x 从 3 -> 1,对应矩阵:
1   2  3  4  5
14  0  0  0  6
13  0  0  0  7
12 11 10  9  8

e. 再次往右:
填充右侧的空格:

1    2  3   4  5
14  15  16  17 6
13   0  0   0  7
12  11  10  9  8

以此类推……

最终矩阵:

1 2 3 4 5

14 15 16 17 6

13 20 19 18 7

12 11 10 9 8

⑤目标值:

print(ans[r-1][c-1])
  • ( r = 2, c = 2 ),对应矩阵的索引为 ( (1, 1) )。
  • 值为 15

运行结果
在这里插入图片描述


http://www.kler.cn/a/430368.html

相关文章:

  • 数据结构:包装类和泛型
  • 游戏关卡设计的常用模式
  • Mysql - 多表连接和连接类型
  • uniapp 导入uview-plus,使用组件出现,页面出现<up-parse>元素不存在,请检查你的代码
  • 域名注册网国际域名与国内域名的区别
  • NOVA:AutoRegressive Video Generation Without Vector Quantization——自回归视频生成无需向量量化
  • 【服务器部署应用由http协议切换为https】
  • 【MARL】MAT论文阅读笔记
  • 【docker集群应用】Docker Compose
  • 沃丰科技智能客服在跨境电商独立站中的核心角色
  • 在Ubuntu上使用docker compose安装N卡GPU的Ollama服务
  • 什么是云原生数据库 PolarDB?
  • Linux学习笔记14 了解磁盘:何为HDD,SSD?sata?PCIE?分区,MBR,GPT (上)
  • vue3 rective 全家桶,to类了解 (1)
  • 项目实践----Spring Boot整合Kafka,实现单条消费和批量消费
  • 河南省的教育部科技查新工作站有哪些?
  • SpringBoot篇(缓存层)
  • 《数据结构》(应用题)
  • Android 因为混淆文件配置,打release包提示running R8问题处理
  • 从0开始边做边学,用vue和python做一个博客,非规范化项目,怎么简单怎么弄,跑的起来有啥毛病解决啥毛病(三)
  • Logstash stopped processing because of an error: (SystemExit) exit
  • 【系统设计】俭约架构七大法则
  • 什么是 Merkle 树
  • Redis探秘Sentinel(哨兵模式)
  • 讲讲什么是 JSX ?
  • Linux Ubuntu 安装配置RabbitMQ,springboot使用RabbitMQ