题目链接:HDU 4920
【题目大意】
简单的两个 n x n的矩阵相乘, 但是对时间要求比较苛刻。
因为c++默认数据优先按行存储,对c理解较深的同学也知道,数组在内存中是用一段连续的空间保存二维数组的,所以按行取元素比按列取元素要快
【代码分析】
一般正常人的思维,二维数组的相乘是这样写的,不就是模拟矩阵相乘嘛~
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
int sum = 0;
for(int k=0;k<n;k++){
sum += (matrixA[i][k]*matrixB[k][j]);
}
ans[i][j] = sum;
}
可是对于对时间要求比较严格的这个题目来说,就太慢了,超时!
因此,如上所述,利用c++默认数据优先按行存储,按行取元素比按列取元素要快这一特点,我们可以这样来写矩阵的相乘
memset(ans,0,sizeof(ans)); //记住要先清零
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
for(int j=0;j<n;j++){
ans[i][j] += (matrixA[i][k]*matrixB[k][j]);
}
仔细对照上下两个代码,可以自己举个例子模拟下算法的运行。
可以看出,下面的代码充分利用了 系统的储存特点 , 使得每次ans【】【】数组的求和 , 几乎都是沿着“内存条”进行定位赋值的。
这样这个题基本上就 OK 了。
【源代码】
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 810;
int matrixA[maxn][maxn];
int matrixB[maxn][maxn];
int ans[maxn][maxn];
int main(){
int n;
while(scanf("%d",&n)!=EOF ){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&matrixA[i][j]);
matrixA[i][j]%=3; //先进行取余操作
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&matrixB[i][j]);
matrixB[i][j]%=3;
}
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
for(int j=0;j<n;j++){
ans[i][j] += (matrixA[i][k]*matrixB[k][j]);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(j!=0)
printf(" %d",ans[i][j]%3); // 输出时再取余
else
printf("%d",ans[i][j]%3);
}
printf("\n");
}
}
return 0;
}