专题十 矩阵问题
(2017·11月浙江省选考)由数组a生成数组b的方法描述如下:
1)将数组a中的n个元素依次分割出若干个数据块,每个数据块有m×m个元素,m最大值为8,最小值为2。分割时,按尽可能大的数据块进行分割;
2)对每个分割出的数据块用“方阵转换法”进行转换,每次转换后得到的数据块依次存储在数据b中;
3)数组a分割后的剩余元素(个数小于4),直接依序存储到数组b中。
例如n=140时,可依次分割出3个数据块,元素的个数分别为64(8×8)、64(8×8)、9(3×3),剩余元素为3个。
“方阵转换法”过程如下:将数据块中m×m个元素按行序排列成一个数字方阵,从该数字方阵中按列序得到转换后元素的次序。以3×3数据块为例,转换过程如下图所示:
小明依据上述描述设计了如下VB程序。请回答下列问题:
(1)当n=120时,分割出的第3个数据块元素个数为__________。
(2)请在划线处填入合适的代码。
Const n = 120
Dim a(1 To n) As Integer
Dim b(1 To n) As Integer
Private Sub Command1_Click()
Dim m As Integer, i As Integer
Dim Start As Integer ′当前未分割数据的第1个元素下标
Dim Left As Integer ′当前未分割数据的个数
Dim pa As Integer ′数组a的下标
Dim pb As Integer ′数组b的下标
′读取n个转换前的数据,依次存储到a(1)、a(2)、……a(n)中,代码略
m = 8
Start = 1
Left = n
Do While Left > 3
If Left < m * m Then
m = ______①____
Else
pa = Start
pb = Start
For i = 1 To m * m
b(pb) = a(pa)
pb = pb + 1
If i Mod m = 0 Then
____②______
Else
pa = pa + m
End If
Next i
____③______
Start = Start + m * m
End If
Loop
For i = Start To n
b(i) = a(i)
Next i
′依次输出转换后数据b(1)、b(2)、……b(n)中,代码略
End Sub
解析 n=120 时,可依次分割出3 个数据块,元素的个数分别为64(8×8)、49(7×7)、4(2×2),剩余元素为3 个。所以第3 个数据块为4 个元素。剩余数量Left < m * m,意味着当前剩余数量不够分割成m×m。下一次尝试m-1方块。例如left=50,m=8,不够分割成8×8,下依次尝试7×7。通过变量i,找出变量i 和下一次数组a 下标之间的关系。通过观察发现每一段pa 的值公差都为3,只需要计算出每一段的首项,该段后面的依次pa+3 即可。分析得出,每一段首项下标 pa=i3+1,后面的依次为pa=pa+3。推广到n 个数据,m×m 方阵中。每一段首项下标 pa=im+start,后面的依次为pa=pa+m。分割之后剩余数量left 减去m*m。
答案 (1)4 (2)①m=m-1 或m=int(sqr(left))
②pa=start+im或pa=start+i/m 或pa=pa-(m-1)*m+1 或pa=start+(pa-start+1) mod m
③left=left-m*m
1.矩阵中所有数据均存储在一个数组中,从第1列开始先存储一行,接着再存储下一行。
2.一个m行n列的数组,在列表框中输出时,用一个字符串变量表示一行,共循环m次。他是一张二维表。一般来说,用i表示某个元素所处的行,用j表示某个元素所处列。
3.矩阵的问题就是研究存储数组元素下标与他所在行和列的关系。
1.矩阵中某个元素的位置跟他前面有完整行数及所在列数有关,若矩阵的大小为m行n列,矩阵问题就是研究矩阵元素位置(i,j)和数组下标pa对应关系,pa=(i-1)*n+j,表达的含义是该元素处在第i行,说明他前面有i-1个完整行,该元素处在第j列,说明除了完整的行,还有j列是零头。
2.通常用双重循环来遍历整个矩阵,变量i和j表示行和列,也可以用一重循环输出,但此时循环变量表示数组下标。代码如下。
For i = 1 To m
s =" "
For j = 1 To n
s = s + a(i - 1) * n + j
Next j
List1.AddItem s
Next i
For i = 1 To m * n
s = s + a(i)
If i Mod n = 0 Then
List1.AddItem s
s =" "
End If
Next i
3.若用一重循环来遍历m行n列矩阵,则下标为i数组元素所处行为(i-1)n,他所处的列为(i-1)Mod n+1
【例】 编写“矩形面积”程序,实现如下功能:按一定比例随机生成a(1)至a(100)数组元素的值:0或1(0多1少);将这100个数组元素,按行依次转化为10×10的二维阵列;当数组元素的值为0时显示成“□”,当数组元素的值为1时显示成“◆”,并在列表框List1 中输出。寻找阵列中,由“□”字符构造出的最大面积的矩形,在标签Label1中显示最大面积所占的单位数。程序运行界面如图所示。实现上述功能的VB代码如下:
Dim a(1 To 100) As Integer
Private Sub Command1_Click()
Dim i As Integer, s As Integer, smax As Integer
′用于随机生成数据,并将阵列按规则在列表框中输出,该部分功能的代码略。
smax = 0
For i = 1 To 100
If a(i) = 0 Then s = search(i)
If s > smax Then smax = s
Next i
Label1.Caption = “最大面积的矩形,占” + Str(smax) +“个单位。”
End Sub
Function search(i As Integer) As Integer
Dim x As Integer, x1 As Integer, xend As Integer
Dim y As Integer, y1 As Integer Dim s As Integer
x = (i - 1) Mod 10 + 1 ′起始列号
y = (i - 1) 10 + 1 ′起始行号
x1 = x :y1 = y :xend = 10
search = 0
Do While y1 <= 10
If__a((y1__-__1)__*__10__+__x)__=__1__Then__Exit__Do ′判断
x1 = x
Do While x1 <= xend
If a((y1 - 1) * 10 + x1) = 1 Then
x1__=__x1__–__1 ′改错
Else
x1 = x1 + 1
End If
Loop
y1 = y1 + 1
s = (x1 - x) * ( ____①____)填空
If s > search Then search = s
Loop
End Function
请回答下列问题:
(1)根据程序的运行界面,没有Caption属性的控件为__________类(单选,填字母: A.窗体/ B.命令按钮/ C.列表框/ D.标签)。
(2)程序代码中,去除“判断”处语句,是否会影响程序的结果__________(选填:是/否)。
(3)程序代码中,“改错”处的语句有误,请改正。
(4)程序代码中,将“填空”处的语句补充完整。
解析 自定义函数的功能是从第i个位置开始查找最大矩形面积,x和y表示第i个元素所处的行号和列号。查找的过程是先扫描x行中所有列,找到一个不为0的就表示该行的列数,退出内循环。接着再扫描下一行,找出构成一个最大的面积。若删除划线处语句,进入内循环后,也马上退出内循环,此时的列数为0,面积也为0。
答案 (1)C (2)否 (3)x1=Xend+1 或ExitDO
(4)①y1-y
【变式训练】 数组a规模为(m+1)×n,其中a(1)~a(m * n)元素中存储数据,数据中m×n个元素按行序排列成一个数字矩阵如图所示。计算每列数据的和依次存储在m+1行对应的数组元素中。
依据算法思想,设计一个计算并存储的程序,实现该功能的VB程序如下,但加框处代码有错,请改正。
Const m = 6
Const n = 5
Dim a(1 To (m + 1) * n) As Integer
Private Sub Command1_Click()
Dim i As Integer, j As Integer
′读取m×n个正整数,依次存入数组a中,代码略
For i = 1 To n
= sum(i) ′(1)
Next i
′将计算后数据,按m + 1行, n列输出到列表框中,代码略
End Sub
Function sum(y As Integer) As Integer ′函数功能是计算每列数据和
sum = 0
For i = ′(2)
sum = sum + a(i)
Next i
End Function
解析 每列的和放在m+1行,因此他前面有完整的m行,在自定义函数中,计算y列的和,分别为y,y+n,y+2*n等等。
答案 (1)a(m*n+i) (2)y to m*n Step n
1.编写VB程序,实现如下功能:在文本框Text1中输入整数n(1-10),生成n2个10到99之间的随机整数,单击“生成矩阵”按钮Command1,并以n行n列矩阵的形式显示在列表框List1中,再单击“对角线”按钮Command2,则在标签Label1中输出该矩阵对角线(左上角到右下角)上的数值,运行界面如图所示,程序代码如下。
请在划线处填入合适的代码。
Dim i As Integer, n As Integer
Dim a(1 To 100) As Integer
′随机生成n2个10~99之间的整数的代码略
Private Sub Command1_Click() ′将n2个数以矩阵形式显示在List1中
Dim s As String
s = ” ”
For i = 1 To ____①____
s =s + Str(a(i))
If ____②____Then
List1.AddItem s
s = ” ”
End If
Next i
End Sub
Private Sub Command2_Click() ′将对角线上的数输出在Label1中
Dim djx As String
For i = 1 to ____③____
djx= djx + ____④____
Next i
Label1.Caption=djx
End Sub
解析 共有n*n个元素,当i是n倍数的时候,表示一行结束,要输出该行,同时变量初始化。共有n个对角线,他们的下标分别为1,n+2,2n+3,可以找到规律是有多少完整行加列数。
答案 ①n*n ②i Mod n=0 ③n ④a((i-1) n *n+(i-1) Mod n+1)
2.对一个n×n的矩阵以“行”为单位进行升序排序,如下表所示是一个4×4的矩阵以行为单位进行升序排序。
小杜编写了实现上述功能的程序,程序功能如下:程序运行时,在文本框Text1中输入n(1<=n<=10),单击“产生”按钮Command1产生n×n个随机数,随机数的范围为[0,9],随机存储在数组a中,并以矩阵的形式在列表框List1上显示。单击“排序”按钮Command2,对矩阵以“行”为单位进行升序排序,并在列表框List2输出排序后的矩阵。在程序运行界面如下图所示,实现上述功能的VB程序如下,请在划线处填入合适的代码。
Dim n As Integer
Dim a(1 To 100) As Integer
′随机生成数并存储在List1中 代码略
Private Sub Command1_Click() ′按行排序
Dim i As Integer, j As Integer, t As Integer
Dim s As String
s = ” ”
For i = 1 To ______①____
k = i
For j = i + 1 To ____②____
If a(j) < a(k) Then k = j
Next j
If k <> i Then t = a(k): a(k) = a(i): a(i) = t
If I Mod n=0 Then List2.AddItem s :s = ” ”
Next i
End Sub
Private Sub Command2_Click() ′按列排序
Dim i As Integer, j As Integer, t As Integer
Dim s As String
s = ” ”
For i = 1 To i-1
k = i
For j = i + n To ____③____
If a(j) < a(k) Then k = j
Next j
If k <> i Then t = a(k): a(k) = a(i): a(i) = t
If I Mod n=0 Then List2.AddItem s :s = ” ”
Next i
End Sub
解析 n个数需排n-1趟,每一趟的结束位置是该行的最后一个数。同样的,若按列排序,每列的最后一个位置在最后一行。
答案 ①n-1 ②(i-1) [BS)] *n ③(n-1)*n+ (i-1) Mod n +1 step n
3.小岩设计了一个顺时针旋转矩阵的程序,其功能为:运行程序时,在文本框Text1中输入矩阵规模n,点击“产生矩阵”按钮Command1,在列表框List1中显示一个n*n的矩阵,该矩阵数据由从1开始的连续自然数组成。点击“旋转矩阵”按钮Command2,该矩阵顺时针旋转90度并显示在列表框List2中,此后每点一次“旋转矩阵”按钮Command2,列表框List2中显示的矩阵顺时针旋转90度。请完成程序填空。
Dim n As Integer
Dim st As String
Dim a(1 To 100) As Integer
Dim b(1 To 100) As Integer
Private Sub Command1_Click()
′产生矩阵,代码略
End Sub
Private Sub Command2_Click() ′旋转矩阵
For i = 1 To n ′行
st = ” ”
For j = 1 To n ′列
b((i - 1) * n + j) = ____①____
st = st + adj(Str(b((i - 1) * n + j)), 3)
Next j
List2.AddItem st
Next i
End Sub
Function adj(a As String, n As Integer) As String
′在字符串a前加入适当的空格,使a的长度为n位,代码略
End Function
解析 从题图上可知,发生了行号和列号的互换。
答案 ①j+(i-1)*n
4.在美国国家信息交换码中,ASCII值从32到127是可以打印并显示的字符,把这96个字符随机调整次序,生成密码本。根据输入的密钥和明文,单击“加密”按钮Command1,输出密文。基本算法如下。
1)用数组mab分别记录1~96个字符的ASCII值,用数组zm记录对应字符在密码本中位置,如mab(9)=65,表示密码本中第9个字符是“A”,则对应的zm(65)=9;
2)把密钥中每个字符的ASCII值的各个数字进行累加(如Hi分别为(7+2)+(1+0+5)),将累加的和除以9取余数后加7,作为将密码本转换成二维表的列数;
3)每个明文在转换后二维表中位置作为密文,该位置是用十六进制表示的行号和列号。
程序运行的界面如下图所示:
实现上述功能的 VB 程序如下,请回答以下问题:
(1)若输入密钥为“AB”,则根据算法及密码本,字母“A”加密后的密文是____________。
(2)请在划线处填入合适的代码。
Dim Mab(96) As Integer ′存储密码本中每个字符的ASCII值
Dim zm(127) As Integer ′存储ASCII值32至127的字符在密码本数组mab中的下标
Private Sub Form_Load()
′产生密码本及96个字符在密码本中位置,代码略。
End Sub
Function p(s As String) As Integer
Dim i As Integer, t1 As Long
Dim sum As Integer, s1 As String
t1 = 0
i = 1
Do While i <= Len(s)
s1 = Mid(s, i, 1)
t1 = Asc(s1)
____①____
i = i + 1
Loop
p = sum Mod 9 + 7
End Function
Private Sub Command1_Click()
Dim i As Integer, t As Integer, hang As Integer
Dim s As String, s1 As String, Lie As Integer
List1.Clear
s1 = Text1.Text
t = p(s1)
Label5.Caption = ”将密码本换成一张” + Str(t) + ”列的二维表”
i = 1
Do While i <= 96
s = s + Chr(Mab(i)) + ” ”
If i Mod t = 0 Or i = 96 Then
List1.AddItem s
s = ” ”
End If
i = i + 1
Loop
wz = ”123456789ABCDEF”
s = Text2.Text
For i = 1 To Len(s)
s1 = Mid(s, i, 1)
___②____
hang =(t1-1)t+1
lie=(t1-1) Mod t +1
s2 =____③____
Next i
Text3.Text = s2
End Sub
解析 字母AB的值分别65、66,各个数字相加为23,23 Mod 9+7=12,即转换成12列的矩阵,因此字母A在第2行第3列。p函数的功能是,根据输入的密钥s,转换成p列的二维表,把密钥中每个字符的ASCII值的各个数字进行累加,将累加的和除以9取余数后加7,保证列数在[7,15]之间;②要求的是根据明文在密码本中位置,转换成相应的行号和列号,t1就是该字母在密码表中的位置。每个明文在转换后二维表中十六进制的行号和列号作为密文。
答案 (1)23 (2)①sum = sum + t110 Mod 10 ②t1 = zm(Asc(s1)) ③s2 + Mid(wz,hang,1)+Mid(wz,lie,1)
5.试场编排方法:每试场人数30,尾数试场可能不足30,按6行5列的布局编排试场,每个试场的座位号如图a所示。编写一个VB程序实现上述功能:在文本框Text1中输入学生数n,在文本框Text2中输入试场号m,单击“确定”按钮Command1,在列表框中List1中输出第m试场的编排表,程序运行界面如图b所示。
第1列
第2列
第3列
第4列
第5列
第1行
1
12
13
24
25
第2行
2
11
14
23
26
第3行
3
10
15
22
27
第4行
4
9
16
21
28
第5行
5
8
17
20
29
第6行
6
7
18
19
30
图a
图b
(1)999 个学生的考号依次是 001,002,…,998,999。根据上述试场编排方法,可知第 3 试场第 2 行第 3 列的学生考号是________。
(2)小王根据上述算法,设计了一个加密程序,其 VB 代码如下,请在划线处填入合适的代码。
Const k = 30
Function adj(s As String) As String
′功能:在字符串 s 前添加若干个空格,代码略。
End Function
Function convert(n As Integer) As String
′功能:把 n 转字符串,不足 3 位则在前面补 0,代码略。
End Function
Private Sub Command1_Click()
Dim kh(1 To 999) As String
Dim n As Integer, m As Integer, kcs As Integer
Dim i As Integer, j As Integer, line As String
Dim start As Integer, offset1 As Integer, offset2 As Integer
n = Val(Text1.Text)
m = Val(Text2.Text)
For i = 1 To n
kh(i) = convert(i)
Next i
If n Mod k = 0 Then kcs = n 'k Else____①______
If m > kcs Or m < 1 Then
Label3.Caption = ”无该试场!”
Else
____②____
For i = 1 To 6
line = ” ”
offset1 = i
line = line + adj(kh(start + offset1))
For j = 2 To 5
If j Mod 2 = 1 Then
offset1 = offset1 + 12
line = line + adj(kh(start + offset1))
Else
____③____
line = line + adj(kh(start + offset2))
End If
Next j
List1.AddItem line
Next i
End If
End Sub
解析 从语句m > kcs来看,kcs表示最大的试场号,试场号往往从1开始编起,当学生人数不是k的倍数时,是k整数倍加1。Stat表示本试场前面已经有的学生编号,因此是前面所有试场人数之和。学生考号是渐行输出的,因此j表示列号,当j Mod 2 = 0时,从第1行开始到第6行,他与前面一列下标的差值分别为11,9,7,5,3,1,可以发现与i的规律是13-2*i。
答案 (1)074 (2)①kcs = n k + 1 ②start = (m - 1) * k ③offset2 = offset1 + 13 - 2 * i
6.小王用VB编写了一个考场座位编排程序,实现从考生数据库里读出所有学生的姓名和前一次考试成绩,分别存入数组xm和数组cj中,并按成绩从高到低排序后显示在List1中。输入考场规格和考场号,单击考场座位编排按钮Command1后,从第一位考试开始按S型依次安排座位,并在List2中输出该考场的座位表。每个姓名输出占4个汉子字符宽度,运用fm函数来解决此问题,尾试场多余位置显示“空”字。
实现上述功能的VB程序如下,请在划线处填入合适的代码。
′加载所有考生信息代码略
′函数fm代码略
Private Sub Command1_Click()
Dim kc As Integer
Dim p As Integer, q As Integer ′p为行,q为列
′初始化代码略
p = Val(Text1.Text): q = Val(text2.Text): kc = Val(text3.Text)
ks = p * q * (kc - 1)
For i = 1 To p
ks = ks + 1
s = fm(xm(ks), 4)
For j = 1 To q - 1
If j Mod 2 = 1 Then
num = ks + p * 2 * (j + 1) 2 - 1 - (i - 1) * 2
Else
num =____①____
End If
If num > n Then
s = s + fm(”空”, 4)
Else
s = s + ____②____
End If
Next j
List2.AddItem s
List2.AddItem ”-----------”
Next i
End Sub
解析 num表示该学生在数组中位置,i表示行,j表示列。For j = 1 To q – 1只循环了q-1次,每行的第一列已经计算好了,代码是s = fm(xm(ks), 4),因此当j等于1时,实际上输出第2列,那么当j是偶数时,分别是3,5,7等列,可以观察到,他与该行的第1列是j*p的等差数列。
答案 ①ks+1+j*p ②fm(xm(num), 4)
7.将n个元素转换成(nm)*m矩阵(n是m的倍数),例如有42个元素,m=7,则可转换成6*7(6行7列)的矩阵。转换示例如下:
转换前元素次序为:
转换为矩阵如下:
现要在矩阵中寻找一个规模为 3*3 的子方阵,使得该子方阵的各元素之和最大。
(1)若n=25,m=5,则该矩阵中共有 3*3 的子方阵个数为__________ 。(填数字)
(2)实现上述功能的 VB 程序如下,请在划线处填入合适代码。
Private Sub Command1_Click()
Dim a(1 To 100) As Integer
Dim sum(0 To 101) As Long ′sum(i)=a(1)+a(2)+a(3)+…+a(i)
Dim i As Integer, j As Integer, n As Integer, m As Integer, k As Integer
Dim ans As Long, begin As Integer, maxi As Integer
Dim maxsum As Long, s As String
n = Val(Text1.Text)
m = Val(Text2.Text)
If n Mod m <> 0 Then List1.AddItem ”输入数据不符合要求”: Exit Sub
For i = 1 To n
a(i) = Int(Rnd * 50 + 1)
s = s + Str(a(i))
If i Mod m = 0 Then List1.AddItem s: s = ” ”
Next i
k = 3
sum(1) = a(1)
For i = 2 To n ′求 sum(i)
____①____
Next i
maxsum = 0
ans = 0
For i = 1 To n 'm - k + 1
For j = k To m
begin = (i - 1) * m + j - k + 1
maxsum=maxsum+sum(j+(i-1)*m)-
sum(j-k+(i-1)*m)
____②____
maxsum=maxsum+sum(j+(i+1)*m)-sum(j-k+(i+1)*m)
If maxsum>ans Then ans=maxsum: maxi=begin
maxsum = 0
Next j
Next i
s = ” ”
For i = 1 To k
For j = 1 To k
s = s + Str(a( ____③____))
Next j
List2.AddItem s
s = ” ”
Next i
List2.AddItem ”maxsum=” + Str(ans)
End Sub
解析 若n=25,m=5,则该矩阵中有5行5列,从第1列到第3列,第2列到第4列,第3列到第5列,横向可以排3个,同时纵向也可以排3个,因此有9个子矩阵。sum(i)求第i项及以前所有项的和。j + (i - 1) * m显然是该行中子矩阵最后1列的位置,因此。j + (i - 1) * m-k子矩阵第1列的位置。sum(j + (i - 1) * m) - sum(j - k + (i - 1) * m)是该行中子矩阵所有列的和。
②中要填的是下一行(中间一行)的所有列之和。Maxi记录的是最大子矩阵的开始位置,在③中变量i表示行,j表示列。
答案 (1)9 (2)①sum(i) = sum(i - 1) + a(i) ②maxsum = maxsum + sum(j + i * m) - sum(j - k + i * m) ③a(maxi + j - 1 + (i - 1) * m)
8.数组a中存放着1到20间的正整数,要求对其中的元素进行分段排序,在文本框Text2中输入每段元素的个数,在文本框Text3中显示每段降序排序后的数据,其中多余的元素不做处理:具体界面如下图所示:
实现该功能的VB程序如下,请在划线处填入合适的代码:
Dim a(0 To 100) As Integer
Const high = 16
Private Sub Form_Load()
′产生high 个随机数,并显示在文本框Text1中,代码略
End Sub
Private Sub Command1_Click()
Dim p As Integer, q As Integer, t As Integer
Dim m As Integer, n As Integer, k As Integer
m = Val(Text2.Text)
For i = 1 To ____①____
c = ” ”
For j = 1 To m-1
______②____
q = i * m
k = sort(p,q)
If a(k) <> a(p) Then
t=a(p):a(p)=a(k):a(k)=t
End If
____③____
Next j
Text3.Text=Text3.Text+” ”+c
Next i
End Sub
Function sort(f As Integer, g As Integer) As Integer
s = f
For i = f+1 To g
If a(i) > a(s) Then
____④____
End If
Next i
sort = s
End Function
解析 ①处显然是求共有多少段。自定义函数sort中,是求f到g中最大数的位置。因此②是从j列开始,找到该段最后一个数。
答案 ①high m 或 int(high / m) ②p = (i - 1) * m + j ③c = c + Str(a(p)) ④s = i
9.用一个5行6列的矩阵表示地图,分别用a数组元素表示,第1行从左到右为a(1)到a(6),依次类推,右下角为a(30)。其中数字0表示不通,数字1表示畅通。现在要从左上角到右下角寻找一条畅通的路径。线路规则如下:
1)路线每个位置只能向右或向下
2)任何一个岔口优先向右走,右侧不通再向下走
3)一条路线中每个位置只能走一次,不能重复算法思路:探路过程中,记录每个位置坐标到数组lu;遇到岔路口(向右向下都通),则记录路口坐标到数组cha;遇到前方无路时,需要返回到上一个路口,标记路口右侧不通;当前方无路,岔路口数组也退回到0,说明整体不通,否则根据规则走到右下角为止,最后输出整体线路坐标。实现算法的程序如下,运行结果如图所示。
回答下列问题:
(1)根据规则,如图迷宫矩阵,将第1行第3列值修改为0,正确路线的第6个位置是a数组的第__________个元素(填数字)。
(2)在程序划线处填上合适代码,使程序完整。
Dim a(1 To 50) As Integer
Private Sub Form_Load()
′生成图形矩阵的数组a各个元素,并在列表框显示,代码略
End Sub
Private Sub Command1_Click()
Dim i As Integer, j As Integer, pos As Integer
Dim cha(1 To 10) As Integer ′记录一条线路中各个岔路口
Dim lu(1 To 10) As Integer ′记录路线经过的位置
pos = 1: j = 0: lu(1) = 1: i = 1
Do While i <= 9′ 第1个和最后1个固定,中间有9个需要路过的路径点
If pos Mod 6 <> 0 And a(pos + 1) = 1 Then
′向右畅通
If pos + 6 <= 30 And a(pos + 6) = 1 Then
′记录岔路口
j = j + 1
____①____
End If
pos = pos + 1
i = i + 1
____②____
ElseIf pos + 6 <= 30 And a(pos + 6) = 1 Then
′向下畅通
pos = pos + 6
i = i + 1
lu(i) = pos
Else ′坐标退回到上一个岔路口
If j = 0 Then Exit Do
Do While lu(i) <> cha(j)
____③____
Loop
a(cha(j) + 1) = 0 ′标记此路口右侧不可用
pos = cha(j)
j = j - 1
End If
Loop
Text1.Text = ” ”
If j = 0 Then
Text1.Text = ”没有畅通道路”
Else
For i = 1 To 10
Text1.Text = Text1.Text + Str(lu(i))
Next i
End If
End Sub
解析 pos表示当前位置,若向右移动,pos+1,若各下移动,pos+6。lu数组记录路线经过的位置,先判断向右,右边的a数组元素为1,作为下一个经过的位置,同时判断一下向下是否可行,如果可行,表示此处有岔路口,下次也可以从此向下找路线,在开始找之前要把该点向右的值修改为0。
答案 (1)21 (2)①cha(j) = pos ②lu(i) = pos
③i = i - 1
课件24张PPT。专题十 矩阵问题(2017·11月浙江省选考)由数组a生成数组b的方法描述如下:
1)将数组a中的n个元素依次分割出若干个数据块,每个数据块有m×m个元素,m最大值为8,最小值为2。分割时,按尽可能大的数据块进行分割;
2)对每个分割出的数据块用“方阵转换法”进行转换,每次转换后得到的数据块依次存储在数据b中;
3)数组a分割后的剩余元素(个数小于4),直接依序存储到数组b中。例如n=140时,可依次分割出3个数据块,元素的个数分别为64(8×8)、64(8×8)、9(3×3),剩余元素为3个。
“方阵转换法”过程如下:将数据块中m×m个元素按行序排列成一个数字方阵,从该数字方阵中按列序得到转换后元素的次序。以3×3数据块为例,转换过程如下图所示:小明依据上述描述设计了如下VB程序。请回答下列问题:
(1)当n=120时,分割出的第3个数据块元素个数为__________。
(2)请在划线处填入合适的代码。
Const n = 120
Dim a(1 To n) As Integer
Dim b(1 To n) As Integer
Private Sub Command1_Click()
Dim m As Integer, i As Integer
Dim Start As Integer ′当前未分割数据的第1个元素下标Dim Left As Integer ′当前未分割数据的个数
Dim pa As Integer ′数组a的下标
Dim pb As Integer ′数组b的下标
′读取n个转换前的数据,依次存储到a(1)、a(2)、……a(n)中,代码略
m = 8
Start = 1
Left = n
Do While Left > 3
If Left < m * m Then
m = ______①____ Else
pa = Start
pb = Start
For i = 1 To m * m
b(pb) = a(pa)
pb = pb + 1
If i Mod m = 0 Then
____②______
Else pa = pa + m
End If
Next i
____③______
Start = Start + m * m
End If
Loop
For i = Start To n
b(i) = a(i)
Next i
′依次输出转换后数据b(1)、b(2)、……b(n)中,代码略
End Sub解析 n=120 时,可依次分割出3 个数据块,元素的个数分别为64(8×8)、49(7×7)、4(2×2),剩余元素为3 个。所以第3 个数据块为4 个元素。剩余数量Left < m * m,意味着当前剩余数量不够分割成m×m。下一次尝试m-1方块。例如left=50,m=8,不够分割成8×8,下依次尝试7×7。通过变量i,找出变量i 和下一次数组a 下标之间的关系。通过观察发现每一段pa 的值公差都为3,只需要计算出每一段的首项,该段后面的依次pa+3 即可。分析得出,每一段首项下标 pa=i3+1,后面的依次为pa=pa+3。推广到n 个数据,m×m 方阵中。每一段首项下标 pa=im+start,后面的依次为pa=pa+m。分割之后剩余数量left 减去m*m。答案 (1)4 (2)①m=m-1 或m=int(sqr(left))
②pa=start+im或pa=start+i/m 或pa=pa-(m-1)*m+1 或pa=start+(pa-start+1) mod m
③left=left-m*m1.矩阵中所有数据均存储在一个数组中,从第1列开始先存储一行,接着再存储下一行。
2.一个m行n列的数组,在列表框中输出时,用一个字符串变量表示一行,共循环m次。他是一张二维表。一般来说,用i表示某个元素所处的行,用j表示某个元素所处列。
3.矩阵的问题就是研究存储数组元素下标与他所在行和列的关系。1.矩阵中某个元素的位置跟他前面有完整行数及所在列数有关,若矩阵的大小为m行n列,矩阵问题就是研究矩阵元素位置(i,j)和数组下标pa对应关系,pa=(i-1)*n+j,表达的含义是该元素处在第i行,说明他前面有i-1个完整行,该元素处在第j列,说明除了完整的行,还有j列是零头。2.通常用双重循环来遍历整个矩阵,变量i和j表示行和列,也可以用一重循环输出,但此时循环变量表示数组下标。代码如下。3.若用一重循环来遍历m行n列矩阵,则下标为i数组元素所处行为(i-1)n,他所处的列为(i-1)Mod n+1
【例】 编写“矩形面积”程序,实现如下功能:按一定比例随机生成a(1)至a(100)数组元素的值:0或1(0多1少);将这100个数组元素,按行依次转化为10×10的二维阵列;当数组元素的值为0时显示成“□”,当数组元素的值为1时显示成“◆”,并在列表框List1 中输出。寻找阵列中,由“□”字符构造出的最大面积的矩形,在标签Label1中显示最大面积所占的单位数。程序运行界面如图所示。实现上述功能的VB代码如下:Dim a(1 To 100) As Integer
Private Sub Command1_Click()
Dim i As Integer, s As Integer, smax As Integer′用于随机生成数据,并将阵列按规则在列表框中输出,该部分功能的代码略。
smax = 0
For i = 1 To 100
If a(i) = 0 Then s = search(i)
If s > smax Then smax = s
Next i
Label1.Caption = “最大面积的矩形,占” + Str(smax) + “个单位。”
End Sub
Function search(i As Integer) As Integer
Dim x As Integer, x1 As Integer, xend As IntegerDim y As Integer, y1 As Integer Dim s As Integer
x = (i - 1) Mod 10 + 1 ′起始列号
y = (i - 1) '10 + 1 ′起始行号
x1 = x :y1 = y :xend = 10
search = 0
Do While y1 <= 10If__a((y1__-__1)__*__10__+__x)__=__1__Then__Exit__Do ′判断
x1 = x
Do While x1 <= xend
If a((y1 - 1) * 10 + x1) = 1 Then
x1__=__x1__–__1 ′改错
Else
x1 = x1 + 1
End If
Loop y1 = y1 + 1
s = (x1 - x) * ( ____①____)填空
If s > search Then search = s
Loop
End Function
请回答下列问题:
(1)根据程序的运行界面,没有Caption属性的控件为__________类(单选,填字母: A.窗体/ B.命令按钮/ C.列表框/ D.标签)。
(2)程序代码中,去除“判断”处语句,是否会影响程序的结果__________(选填:是/否)。(3)程序代码中,“改错”处的语句有误,请改正。
(4)程序代码中,将“填空”处的语句补充完整。解析 自定义函数的功能是从第i个位置开始查找最大矩形面积,x和y表示第i个元素所处的行号和列号。查找的过程是先扫描x行中所有列,找到一个不为0的就表示该行的列数,退出内循环。接着再扫描下一行,找出构成一个最大的面积。若删除划线处语句,进入内循环后,也马上退出内循环,此时的列数为0,面积也为0。答案 (1)C (2)否 (3)x1=Xend+1 或ExitDO
(4)①y1-y【变式训练】 数组a规模为(m+1)×n,其中a(1)~a(m * n)元素中存储数据,数据中m×n个元素按行序排列成一个数字矩阵如图所示。计算每列数据的和依次存储在m+1行对应的数组元素中。依据算法思想,设计一个计算并存储的程序,实现该功能的VB程序如下,但加框处代码有错,请改正。
Const m = 6
Const n = 5
Dim a(1 To (m + 1) * n) As Integer
Private Sub Command1_Click()
Dim i As Integer, j As Integer
′读取m×n个正整数,依次存入数组a中,代码略 sum = sum + a(i)
Next i
End Function解析 每列的和放在m+1行,因此他前面有完整的m行,在自定义函数中,计算y列的和,分别为y,y+n,y+2*n等等。
答案 (1)a(m*n+i) (2)y to m*n Step n