2023年Pre题目回忆版及我的3A答案回忆版

文件在我的 GitHub

1.supaltitude

骑手在初始海拔为 \(0\) 的原点,依次读入数组大小 \(n\) 和相邻两地点的海拔差 \(gain[n]\),输出骑手所经过的最高海拔

数据范围 \(1 \le n \le 64\)

\(-128 \le gain[n] \le 128\)

思路:题目所求即为数组最大前缀和,维护一个变量保存当前前缀和,并维护最大值即可,没有开辟数组空间的必要

:保存最高海拔的前提是数组的下标连续,而不能像买卖理财产品,只在有收益的时候售出。也即如下的代码思路是错误的(虽然我相信聪明的大家都想到了)

1
2
3
4
5
if (data > 0) { // data is the input value
sum += data;
} else {
// do nothing
}

代码挖空:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text
main:
# get n
# set prefix sum, maximum value and loop var

for_loop:
# get data
add $s1, $s1, $t1
if:
# no need to update, jump to 'else' label
move $s2, $s1 #update
else:
addi $t0, $t0, 1 # DONT FORGET TO INCREMENT LOOP VAR
bne $t0, $s0, for_loop

loop_end:
# DONT FORGET TO PRINT

此外建议大家在编写汇编代码时多用伪指令,能显著加快编程速度(毕竟这就是伪指令的使命)

blt 省去了 sltbeq 的使用,将两条指令合为一条;moveadd 指令少一个操作数;liaddi 少两个操作数等等

2.noDescendSequence

识别16bit输入从高位到低位每4bit组成的4位序列是否为不下降序列

信号 方向 说明
data[15:0] input 代表4位4bit输入
result out 输出结果:是否为不下降序列

思路:本题不涉及时序逻辑,直接取 data 的对应位进行比较即可。一行代码我就不贴出来了(

3.tetris

模拟8位俄罗斯方块游戏设计 Mealy 状态机

信号 方向 说明
input[7:0] I 八位独热码,模拟掉落一个俄罗斯方块
reset I 异步复位
clk I 时钟信号
output[1:0] O 输出状态

reset为异步复位,当reset为高电平时,状态恢复到一开始状态

状态:输出01表示输入位置已有方块,放置无效,保持原状态

输出10表示有效放置

输出11表示消去一行

思路

第一步也是最重要的一步,确定状态机类型。一时不慎,满盘皆输!!!

方块的摆放情况数为 8 位二进制数的数量 \(2^8\),再考虑每次独热码输入有 8 种,有效的状态转移真值表共约 \(8 \times 2^8\) 行,再考虑到无效的状态转移行,故采用真值表刻画状态转移的方式应该不是题目意图(当然如果你毅力超群,我致以崇高敬意)。我采取的方案是用当前的方块摆放情况表示状态,在 Mealy 状态机的输出模块再转换成 output[1:0]

放置方块的行为让我联想到二进制的按位运算。判断某位是否已有方块,只需将输入和当前方块按位与,结果非 0 即为无效放置。而更新状态,只需将输入和当前方块放置状态按位或,注意特判放满后清空即可。

Tips

注意到 logisim 中寄存器初值为 0,所以不用进行寄存器的初始化。

注意判断复位方式是同步复位还是异步复位。异步复位在 logisim 中的实现较为简单。

此外,注意判断时钟是输入还是自带信号。

还有一件事(成龙历险记老爹音),题目要求的电路外观似乎不同于三输入一输出的默认外观,只需将左边三输入向下移动一格即可,外观的线不是很重要。

电路外观如图(已隐去部分内容)

最后,祝大家上机顺利,学有所获!