算法问题求解
1. 对于两个给定的 n 阶方阵 A 和 B,计算 A 和 B 的乘积。
实验原理:
① 矩阵相乘只有在第一个矩阵的列数和第二个矩阵的行数相同时才有意义。矩阵 C 的行数等于矩阵 A 的行数,C 的列数等于 B 的列数。
② 乘积 C 的第 i 行第 j 列的元素等于矩阵 A 的第 i 行的元素与矩阵 B 的第 j 列
对应元素乘积之和。
输入格式 A(m,s) B(s,n)
输出格式 C(m,n)
分析:
- 输入是两个矩阵,且只有大小参数情况,我的程序选择用随机数生成具体数据;
- 对于两个矩阵要先判断是否可以相乘,不能则需要提示重新输入;
- 用二维数组对矩阵进行模拟,所以要用大量的双for循环遍历操作;
- 矩阵相乘,用矩阵的相应元素的乘积和对数学计算过程模拟;
- 最后将两个原矩阵以及相乘的结果矩阵全部显示。
实现代码:
给了大家非常详细的注释,应该都可以看懂哈!!! 0.0
#include <stdio.h>
#include <stdlib.h>
int main() {
int i,j,k,sum=0,m,s1,s2,n;
/*i,j,k均用于for循环,sum用于数据计算,m,s1,s2,n分别是输入的两个矩阵的行数与列数*/
printf("请输入两个矩阵大小参数,格式为:A(m,s) B(s,n) 中间以空格分开,行列数自定义:");
scanf("A(%d,%d) B(%d,%d)",&m,&s1,&s2,&n);
printf("\n");
/*用m,s1,s2,n对输入参数接收,用于下面的二维矩阵a和b的大小定义*/
if(s1!=s2)
{
printf("您输入的矩阵不能相乘,请再次运行重新输入!");
/*判断输入的两个矩阵是否可以相乘,不满足条件直接退出*/
return 0;
}
int a[m][s1],b[s2][n],re[m][n];
/*根据输入的参数,定义待乘的两个二维数组a和b,以及相乘结果矩阵re*/
for(i=0;i<m;i++)
for(j=0;j<s1;j++)
a[i][j] = rand() % 100 + 1;
for(i=0;i<s2;i++)
for(j=0;j<n;j++)
b[i][j] = rand() % 100 + 1;
/*由于并没有对二维数组初始化,这里直接生成1-100之间的随机数作为数据*/
printf("矩阵A的数据:\n");
for(i=0;i<m;i++)
{
for(j=0;j<s1;j++)
{
printf("%-5d ",a[i][j]);
}
printf("\n");
}
printf("\n");
printf("矩阵B的数据:\n");
for(i=0;i<s2;i++)
{
for(j=0;j<n;j++)
{
printf("%-5d ",b[i][j]);
}
printf("\n");
}
printf("\n");
/*将随机生成的数组a和b用两个for循环全部打印出来,可用于检验正确性*/
for(i=0;i<m;i++)
for(j=0;j<n;j++)
/*两个for循环实现先从re[0][0]开始选定结果数组的某个元素*/
{
for(k=0;k<s1;k++)
sum += a[i][k]*b[k][j];
/*数学方法计算出a数组的第i行与b数组的第j行乘积和,赋值给sum,这一步可以写成一个函数,但是参数可能太多,就没有用函数调用实现*/
re[i][j] = sum;
sum = 0;
/*用sum给结果数组赋值后,将sum清零,继续用于下一个元素的计算*/
}
/*到这里完成所有的计算工作*/
printf("计算结果矩阵是:\n");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf("%-5d\t",re[i][j]);
}
printf("\n");
}
/*将结果数组re的所有元素全部输出*/
return 0;
}
运行演示:
-
以A(2,2) B(2,3) 作为矩阵大小测试,具体数据由1-100的随机数生成:
-
检验:
-
以A(10,12) B(12,8) 作为矩阵大小测试,矩阵大小自定义,程序具有普遍性:
2. 从具体到抽象设计循环,利用列表模拟探索循环规律,使得输出结果如下图所示。
1
5 2
8 6 3
10 9 7 4
…… ……
或者
1
6 2
10 7 3
13 11 8 4
15 14 12 9 5
…… ……
分析:
- 当输出为 4 行 4 列时,假设 n=4,需要输出 1,2,3,4,……,10,共 10个数;
- 对于输入数字n的值,输出呈下三角形式输出,所以可以用二维数组遍历实现;
- 在定义二维数组之前要先计算,获取到应该设计的二位数组大小参数;
- 这道题难在如何对二维数组数据的满足形式要求,正确赋值;
- 在开始编程之前可以先用数学表示的方法,弄清楚数据的排列关系,如何一般化表示;
- 我打算先表示第一列的数字,然后其他数组元素均用同行左边的元素来表示;
- 赋值结束只需要下三角双for循环输出即可,上三角的数据不用管。
实现代码:
还是非常详细的注释,应该都可以看懂哈!!! 0.0
#include <stdio.h>
#include <stdlib.h>
int main() {
int n,i,j;
/*定义用于接收三角形队列的数字总数n,循环变量i,j*/
printf("请输入类似1,3(3=1+2),6(6=1+2+3),10(10=1+2+3+4+5),15...的值,实现按格式输出1-n:");
scanf("%d",&n);
for(i=1;;i++)
if(i*(i+1)/2 == n)
break;
/*用数学方法测出用于存储三角形队列的二维数组大小参数i*/
int num = i;
int a[num][num];
/*用num表示数组参数大小并定义该数组,i继续用于循环*/
for (i = 0 ; i < num ; i++)
for (j = 0 ; j < num ; j++)
a[i][j] = 0;
/*先对二维数组的每一个元素赋值0*/
a[0][0] = 1;
/*无论什么样的三角形,第一个始终是1,先定义*/
/*下面的for循环用于从第二行开始先对第一列每个元素赋值*/
for(j=1;;j++)
{
a[j][0] = a[j - 1][0] + num-j+1;
/*用上上一行数据间接表示下一行*/
if(a[j][0] == n)
break;
/*当最后一个元素大小为n的时候结束*/
}
/*下面的两个for循环用于对从第二列开始的所有元素赋值*/
for (j = 1 ; j < num ; j++)
for (i = 0 ; i < num ; i++)
a[i][j] = a[i][j-1] -((j+1+num)-(i+2));
/*这里的(j+1+num)-(i+2)是我总结出来的一般性规律,可以验证一下*/
/*下面对于数组选择性输出下三角全部元素*/
printf("\n计算结果显示如下:\n");
for (i = 0 ; i < num ; i++)
{
for (j = 0 ; j <= i ; j++)
printf("%d\t",a[i][j]);
printf("\n");
}
return 0;
}
运行演示:
- 以15(15=1+2+3+4+5)为测试数据:
- 以36(36=1+2+3+4+5+6+7+8)为测试数据,程序设计具有普遍性,测试数据n只要满足n = 1+2+3+4+5+6+7+…+ i ,都可以正确显示