矩阵,二维数组,两个矩阵相乘,他们必相容,矩阵A[M][K]和矩阵B[K][N]相称等于C[M][N],A矩阵的列等于B矩阵的行,则它两相容。
A[2][2]={{1,2}{4,5}}
B[2][2]={{6,7}{8,9}}
C[2][2];
A*B=C
两个矩阵相乘,变成了8个矩阵相乘相加的关系。
相当于1个矩阵变成了4个小矩阵,缩小了规模,体现了分治的思想。(缩小到每个矩阵只有一个元素,停止)
A*B等于以下内容
C[0][0]=A[0][0]*B[0][0]+A[0][1]*B[1][0];
C[0][1]=A[0][0]*B[1][0]+A[0][1]*B[1][1];
C[1][0]=A[1][0]*B[0][0]+A[1][1]*B[1][0];
C[1][1]=A[1][0]*B[1][0]-A[1][1]*B[1][1];
先来一段暴力求解,证明时间复杂度O(n^3)伙感觉是m*n*k,估计优化下,忽略低阶啊常量啊什么的,就成了n^3,这个也还能理解)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int A[2][2] = { {1,2} ,{4,5} };
int B[2][2] = { {6,7} ,{8,9} };
int C[2][2] = { 0 };
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
return 0;
}
#include<stdio.h>
int main()
{
int A[2][2] = { {1,2} ,{4,5} };
int B[2][2] = { {6,7} ,{8,9} };
int C[2][2] = { 0 };
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
return 0;
}
重点来了;分治算法
这种分8次的递归,我竟然写不出来,网上的资料代码,太长,我看不下去,8次递归乘法优化后是7次递归乘法(数学逻辑,看见一堆数字我也不想看了),时间复杂度由O(0^3)优化成O(0^2.81);(关于这个难点,我想一年后再来解决,因为我现在的水平太low,解决它太费时间);
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
然后我看了网上的另一个递归逻辑,
#include<stdio.h>
#define n 4
#define k 4
int a[n][k] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
int b[k][n] = { 10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160 };
int c[n][n] = { 0 };
int div(int cx1, int cy1);
int up(int cx,int cy);
int left(int cx,int cy);
int main()
{
div(0, 0, 0, 0);//C数组起点C[0][0],终点C[n-1][n-1],终点也是边界。
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%5d ", c[i][j]);
}
printf("\n");
}
return 0;
}
int div(int cx, int cy)
{
if (cx == n - 1) {//边界,余下的部分只有一个点,
for (int i = 0; i < k ; i++) {
c[n - 1][n - 1] += a[n - 1][i] * b[i][n - 1];
}
return 0;
}
else {
for (int i = 0; i < k ; i++) {
c[cx][cy] += a[cx][i] * b[i][cy];
}//解决左上角的一个点
up(cx,cy);//解决最上一行
left(cx,cy);//解决最左一列
cx++;
cy++;
div(cx, cy);//解决余下的一部分
}
}
int left(int cx,int cy)
{
cx++;
if (cx == n) return 0;
else {
for (int i = 0; i < k; i++) {
c[cx][cy] += a[cx][i] * b[i][cy];
}
left(cx, cy);
}
}
int up(int cx, int cy)
{
cy++;
if (cy == n) return 0;
else {
for (int i = 0; i < k; i++) {
c[cx][cy] += a[cx][i] * b[i][cy];
}
up(cx, cy);
}
}
#define n 4
#define k 4
int a[n][k] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
int b[k][n] = { 10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160 };
int c[n][n] = { 0 };
int div(int cx1, int cy1);
int up(int cx,int cy);
int left(int cx,int cy);
int main()
{
div(0, 0, 0, 0);//C数组起点C[0][0],终点C[n-1][n-1],终点也是边界。
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%5d ", c[i][j]);
}
printf("\n");
}
return 0;
}
int div(int cx, int cy)
{
if (cx == n - 1) {//边界,余下的部分只有一个点,
for (int i = 0; i < k ; i++) {
c[n - 1][n - 1] += a[n - 1][i] * b[i][n - 1];
}
return 0;
}
else {
for (int i = 0; i < k ; i++) {
c[cx][cy] += a[cx][i] * b[i][cy];
}//解决左上角的一个点
up(cx,cy);//解决最上一行
left(cx,cy);//解决最左一列
cx++;
cy++;
div(cx, cy);//解决余下的一部分
}
}
int left(int cx,int cy)
{
cx++;
if (cx == n) return 0;
else {
for (int i = 0; i < k; i++) {
c[cx][cy] += a[cx][i] * b[i][cy];
}
left(cx, cy);
}
}
int up(int cx, int cy)
{
cy++;
if (cy == n) return 0;
else {
for (int i = 0; i < k; i++) {
c[cx][cy] += a[cx][i] * b[i][cy];
}
up(cx, cy);
}
}