POJ 3213 PM3 矩阵乘法优化

PM 3
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 3298 Accepted: 1151

Description

USTC has recently developed the Parallel Matrix Multiplication Machine – PM3, which is used for very large matrix multiplication.

Given two matrices A and B, where A is an N × P matrix and B is a P × M matrix, PM3 can compute matrix C = AB in O(P(N + P + M)) time. However the developers of PM3 soon discovered a small problem: there is a small chance that PM3 makes a mistake, and whenever a mistake occurs, the resultant matrix C will contain exactly one incorrect element.

The developers come up with a natural remedy. After PM3 gives the matrix C, they check and correct it. They think it is a simple task, because there will be at most one incorrect element.

So you are to write a program to check and correct the result computed by PM3.

Input

The first line of the input three integers NP and M (0 < NPM ≤ 1,000), which indicate the dimensions of A and B. Then follow N lines with P integers each, giving the elements of A in row-major order. After that the elements of B and C are given in the same manner.

Elements of A and B are bounded by 1,000 in absolute values which those of C are bounded by 2,000,000,000.

Output

If C contains no incorrect element, print “Yes”. Otherwise print “No” followed by two more lines, with two integers r and c on the first one, and another integer v on the second one, which indicates the element of C at rowr, column c should be corrected to v.

Sample Input

2 3 2
1 2 -1
3 -1 0
-1 0
0 2
1 3
-2 -1
-3 -2

Sample Output

No。
1 2
1

Hint

The test set contains large-size input. Iostream objects in C++ or Scanner in Java might lead to efficiency problems.


题意:给矩阵A,B,C。C == A*B,但是C中可能有一个数据是错的。没有错误输出Yes,有就输出No并输出几行几列和正确答案。


解法,暴力矩阵乘法可过,直接写就行


另一种,写矩阵乘法的时候,会发现A的每个数都会乘B中某一行的每个数字。这样,可以处理B的每一行的和,求的A*B的每一行的和与C的每一行的和进行比较,如果相等就没有错误数据,不想等就有错误数据,对出现错误的这一行与B进行矩阵乘法找出那个数据就行了。感觉还是很巧妙的。


暴力的写法已注释

/*暴力求解
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>

using namespace std;

const int N = 1000+10;

int A[N][N],B[N][N],C[N][N];

int main()
{
    int n,p,m;
    scanf("%d%d%d",&n,&p,&m);
    for(int i = 1;i <= n;i++) for(int j = 1;j <= p;j++) scanf("%d",&A[i][j]);
    for(int i = 1;i <= p;i++) for(int j = 1;j <= m;j++) scanf("%d",&B[i][j]);
    for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) scanf("%d",&C[i][j]);
    int tmp;
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= m;j++){
            tmp = 0;
            for(int k = 1;k <= p;k++)
                tmp += A[i][k]*B[k][j];
            if(tmp != C[i][j]){
                printf("No\n%d %d\n%d\n",i,j,tmp);
                return 0;
            }
        }
    }
    printf("Yes\n");
    return 0;
}*/

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;
const int N = 1000+10;
int A[N][N],B[N][N],C[N][N];
int b_c[N],c_c[N];
int main(void)
{
    int n,p,m;
    memset(b_c,0,sizeof b_c);
    memset(c_c,0,sizeof c_c);
    scanf("%d%d%d",&n,&p,&m);
    for(int i = 1;i <= n;i++) for(int j = 1;j <= p;j++) scanf("%d",&A[i][j]);
    for(int i = 1;i <= p;i++) for(int j = 1;j <= m;j++) scanf("%d",&B[i][j]),b_c[i] += B[i][j];
    for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) scanf("%d",&C[i][j]),c_c[i] += C[i][j];
    bool flag = false;
    int col; ///记录哪一行出错
    for(int i = 1;i <= n;i++){     ///查找哪一行出错
        int tmp = 0;
        for(int j = 1;j <= p;j++){
            tmp += A[i][j]*b_c[j];
        }
        if(tmp != c_c[i]) {col = i;flag = true;break;}
    }
    if(!flag) puts("Yes");
    else{
        puts("No");
        for(int i = 1;i <= m;i++){ ///进行矩阵乘法查找就行
            int tmp = 0;
            for(int j = 1;j <= p;j++){
                tmp += A[col][j]*B[j][i];
            }
            if(tmp != C[col][i]){
                printf("%d %d\n%d\n",col,i,tmp);
                //return 0;
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值