您的位置:首页 > 其它

codevs#3147[题解]矩阵乘法2

2016-05-16 17:45 295 查看
题目描述 Description

给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和。
*为防止卡评测,已减小数据范围并调低时限。

输入描述 Input Description

第一行两个正整数n,m。

接下来n行,每行n个非负整数,表示第一个矩阵。

接下来n行,每行n个非负整数,表示第二个矩阵。

接下来m行,每行四个正整数a,b,c,d,表示询问第一个矩阵与第二个矩阵的积中,

以第a行第b列与第c行第d列为顶点的子矩阵中的元素和。

输出描述 Output Description

对每次询问,输出一行一个整数,表示该次询问的答案。

样例输入 Sample Input

3 2

1 9 8

3 2 0

1 8 3

9 8 4

0 5 15

1 9 6

1 1 3 3

2 3 1 2

样例输出 Sample Output

661

388

数据范围及提示 Data Size & Hint

【数据规模和约定】
对40%的数据满足,n <= 100,m <= 1000。

对100%的数据满足,n <= 800,m <= 10000,输入数据中矩阵元素 < 100,a,b,

c,d <= n。
数据有梯度。

80′暴力:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
struct Mart
{
int a[801][801];
}A,B,C;
void Martix(Mart A,Mart B)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
C.a[i][j]+=A.a[i][k]*B.a[k][j];
}
//	printf("%d ",C.a[i][j]);
}
//printf("\n");
}
}
int x1,x2,y1,y2;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&A.a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&B.a[i][j]);
Martix(A,B);
for(int k=1;k<=m;k++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
long long ans = 0;
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
for(int i=x1;i<=x2;i++)
{
for(int j=y1;j<=y2;j++)
{
ans += C.a[i][j];
}
}
printf("%lld\n",ans);
}
return 0;
}


设第一个矩阵的第i行第j列为a[i][j],第二个为b[i][j],根据矩阵乘法的定义,答案为∑(min(a,c)<=i<=max(a,c),min(b,d)<=j<=max(b,d))(∑(1<k<n)a[i][k]*b[k][j]),

时间复杂度为O(n^3),会超时.

所以我们必须将其变形:

加法结合律,得:∑(1<k<n)(∑(min(a,c)<=i<=max(a,c))(∑(min(b,d)<=j<=max(b,d))(a[i][k]*b[k][j]))),

乘法结合侓,得:∑(1<k<n)((∑(min(a,c)<=i<=max(a,c))a[i][k])*(∑(min(b,d)<=j<=max(b,d))b[k][j])),

时间复杂度为降至O(n^2),但由于要计算m次,还是会超时.

但我们可以发现,∑(min(a,c)<=i<=max(a,c))a[i][k]和∑(min(b,d)<=j<=max(b,d))b[k][j]可以用前缀和来求,

于是时间复杂度再降至O(n),但要额外加上与处理的O(n^2),

所以总时间复杂度为O(mn+n^2).

注意:由于空间限制是64000KB,所以,获得前缀和后不能保留矩阵a和矩阵b,而且,虽然变量类型要用长整型,但是前缀和只能用整型,用长整型的只能是答案.

附代码:
#include<iostream>

using namespace std;

int n,m,i,j,matrix1[2001][2001]={},matrix2[2001][2001]={},a,b,c,d;

long long answer;

int main ()

{

cin>>n>>m;

for (i=1;i<=n;i++)

for (j=1;j<=n;j++)

scanf("%d",&matrix1[i][j]);

for (i=1;i<=n;i++)

for (j=1;j<=n;j++)

scanf("%d",&matrix2[i][j]);

for (i=1;i<=n;i++)

for (j=1;j<=n;j++)

matrix1[i][j]+=matrix1[i-1][j];

for (i=1;i<=n;i++)

for (j=1;j<=n;j++)

matrix2[i][j]+=matrix2[i][j-1];

for (i=1;i<=m;i++)

{

scanf("%d %d %d %d",&a,&b,&c,&d);

answer=0;

for (j=1;j<=n;j++)

answer+=(long long)(matrix1[max(a,c)][j]-matrix1[min(a,c)-1][j])*(long long)(matrix2[j][max(b,d)]-matrix2[j][min(b,d)-1]);

cout<<answer<<endl;

}

return 0;

}


ACcode:100scores.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
struct Mart
{
int a[801][801];
}A,B;
int x1,x2,y1,y2;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&A.a[i][j]);
A.a[i][j]+=A.a[i-1][j];
}

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&B.a[i][j]);
B.a[i][j]+=B.a[i][j-1];
}
for(int k=1;k<=m;k++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
long long ans = 0;
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
for(int j=1;j<=n;j++)
ans+=(A.a[x2][j]-A.a[x1-1][j])*(B.a[j][y2]-B.a[j][y1-1]);
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: