POJ 3318 Matrix Multiplication

来源:互联网 发布:软件测试服务 编辑:程序博客网 时间:2024/05/09 20:21
Matrix Multiplication
Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 6414Accepted: 1186

Description

You are given three n × n matrices A, B and C. Does the equation A × B = C hold true?

Input

The first line of input contains a positive integer n (n ≤ 500) followed by the the three matrices A, B and C respectively. Each matrix's description is a block of n × n integers.

It guarantees that the elements of A and B are less than 100 in absolute value and elements of C are less than 10,000,000 in absolute value.

Output

Output "YES" if the equation holds true, otherwise "NO".

Sample Input

21 02 35 10 85 110 26

Sample Output

YES

Hint

Multiple inputs will be tested. So O(n3) algorithm will get TLE.

Source

 
转至:http://hi.baidu.com/redcastle/blog/item/13ec9f255d50966234a80f13.html

关于八月POJ月赛problem B(3381)的解题总结

一、      题目要求

给定三个矩阵:ABC,判断A*B是否等于C

二、      分析

题目很直观,就是矩阵乘法,但是两个矩阵直接相乘需要O(n^3)的时间复杂度,假设A*B的结果存放在AB矩阵中,实例代码如下:

for(int i=0;i<n;i++)

       for(int j=0;j<n;j++)

       {

              AB[i][j] = 0;

              for(int k=0;k<n;k++)

                     AB[i][j] += A[i][k]*B[k][j];

       }

       然后在用O(n^2)的时间进行ABC的比较,返回是否相等。比赛时很容易想到这个解法,但是超时是必然的,因为题目中矩阵的行列都不大于250O(n^3)的时间算一个很大的矩阵相乘,要用超过2秒的时间。

       怎么改进呢?

       用压缩矩阵再比较的方法:

       设一个行向量XX1*n的矩阵,若A*B等于C则必有X*A*B等于X*C,虽然多乘了一个向量,但是时间复杂度却降低到了O(n^2)了。

       这样解的实质是把一个方阵压缩成了一个行向量,向量的每一个元素都是原矩阵该列的的和,也就是说用和来比较。这样大大节省了时间。但是带来一个问题:

       如这两个矩阵:

       x x x x x x x x x x                    x x x x x x x x x x

       x x 1 x x x x 1 x x                    x x 0 x x x x 2 x x

       x x x x x x x x x x                    x x x x x x x x x x

       x x 1 x x x x 1 x x                    x x 2 x x x x 0 x x

       ……                                   ……

       x x x x x x x x x x                    x x x x x x x x x x

       用压缩再比较的方法不能得到正确结果。压缩再比较的关键在于怎么样在和中体现原来每个元素的个性。关键就是X行向量怎么设定。题目在比赛结束后提示是一个随机的向量X,就是把X的每个元素设为随机数。我觉得可以把X设为一个递增的向量:{12n},这样更能体现每个元素的个性,而随机有可能在关键点上出现错误。

三、            代码

/*

Problem B: Matrix Multiplication

The author gives an approximate algorithm rather than a precise one.

Randomize a n ×1 matrix X, test if the equation A × B × X = C × X holds true.

If it is not true we can safely say "NO" to this problem.

If it is true, the possibility that  A × B X is extremely little.

*/

/*

上面是北大网站上的提示,用行向量把CAB压缩了,然后怎么体现个性呢,看这一句:

Randomize a n ×1 matrix X

用一个随机的向量。

不过原理在体现个性,所以我用了个更好的方法,吧X定义为:{1,2,3,4,...,n}

这样能更好的体现个性。

  1. #include<cstdio>
  2. #include<memory.h>
  3. typedef long long Int64;
  4. Int64 a[510][510];
  5. Int64 b[510][510];
  6. Int64 c[510][510];
  7. Int64 E[510] = {0};
  8. Int64 e[510] = {0};
  9. Int64 tmp1[510] = {0};
  10. bool eq(int n)
  11. {
  12.        memset(tmp1,0,sizeof(tmp1));
  13.        
  14.        for(int i=0;i<n;i++)
  15.               for(int j=0;j<n;j++)
  16.                      tmp1[i] += a[j][i] * (j+1);//关键部分: *(j+1)就是乘了一个递增的行向量X:{1,2,3,...,n}
  17.        for(int i=0;i<n;i++)
  18.               for(int j=0;j<n;j++)
  19.                      e[i] += tmp1[j]*b[j][i];//以上四个for用于求AB的行向量。
  20.        for(int i=0;i<n;i++)
  21.               if(e[i] != E[i]) return false;
  22.        return true;
  23. }
  24. int main()
  25. {
  26.        int n;
  27.        while(scanf("%d",&n) != EOF)
  28.        {
  29.               for(int i=0;i<n;i++)
  30.                      for(int j=0;j<n;j++)
  31.                             scanf("%I64d",&a[i][j]);
  32.               for(int i=0;i<n;i++)
  33.                      for(int j=0;j<n;j++)
  34.                             scanf("%I64d",&b[i][j]);
  35.               for(int i=0;i<n;i++)
  36.                      for(int j=0;j<n;j++)
  37.                             scanf("%I64d",&c[i][j]);
  38.               
  39.               memset(e,0,sizeof(e));
  40.               memset(E,0,sizeof(E));
  41.                      
  42.               for(int i=0;i<n;i++)
  43.                      for(int j=0;j<n;j++)
  44.                             E[i] += c[j][i] * (j+1);//关键部分: *(j+1)就是乘了一个递增的行向量X:{1,2,3,...,n}
  45.                      
  46.               if(eq(n)) printf("YES/n");
  47.               else printf("NO/n");
  48.        }
  49.        return 0;
  50. }

 

说实话在看到这个以前我是用随机算法,说白了就是死死的取100000次..很明显是很天真的做法,看到以后才知道真巧妙....彻底ORZ...................