HDU 4920 Matrix multiplication(矩阵相乘小优化)
题目链接: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; }