Problem G: Matrix
Time Limit: 2 Sec Memory Limit:128 MBDescription
Input
Output
Sample Input
2
5 3
1 0
2 1
3 3
3 3
0 0
1 0
2 0
Sample Output
3
9
HINT
----------------------------------------------------------------------------------------------------------
解题报告:
以3阶矩阵为例:
|a11 a12 a13| |a11 a21 a31|
B= A*AT = |a21 a22 a23|* |a12 a22 a32| =
|a31 a32 a33| |a13 a23 a33|
|a11*a11+a12*a12+a13*a13 a11*a21+a12*a22+a13*a23 a11*a31+a12*a32+a13*a33|
|a21*a11+a22*a12+a23*a13 a21*a21+a22*a22+a23*a23 a21*a31+a22*a32+a23*a33| |a31*a11+a32*a12+a33*a13 a31*a21+a32*a22+a33*a23 a31*a31+a32*a32+a33*a33|
1)矩阵(方阵)行、列数,最大为 n=100000 ,如果直接申请二维数组会爆掉(10^10).
2)仔细观察题目,发现矩阵中(方阵)最多只有 m=1000 个点为“1”,其余都为“0”。
3)显然,该题的破解就需要从点着手。
- 建立结构体存储点的横,纵坐标(x,y);
- 分析矩阵乘法的规律(上面以3阶矩阵为例):
- x 与 x` 决定矩阵B中第 x 行,第 x` 列的位置;
- 显然,与Axy项相乘的项Ax`y`,y 值必然相等( y==y` );
- 又由 矩阵 乘法规律,当 ( y==y` && x==x` )时,非0点有+1个;
- 而当只有( y==y` ),非0点重复。(+2)
- 【如:a11*a21存在(第1行第2列),则矩阵B第2行第1列(a21*a11也存在)值也非0。】
- 由此,当( y==y`)时,若( x==x` )count++;否则(x!=x`)count+=2;
- 但由此,会引来重复计算问题:
- 【如:a12*a22存在(第1行第2列),则矩阵B第2行第1列(a22*a12也存在)值也非0。】
- 【但由上可知count已经+2了,如果再执行count+=2,就会导致重复。】
- 为了解决这种问题。
- 记录点坐标时,采用快速排序qsort(……)(包含头文件stdlib.h);
- 对记录点坐标的结构体数组排序(由小到大,先按x值排序,次按y值排序);
- 排序后进行 y值比较,判断x的情况,进行count增加。
- 情况如下图:
- 用x1,x2记录(判断x的情况,进行count增加时)的x与x` ;
- 得,判断条件(用来排除重复情况):( ( x>x1 || x`>x2 ) && ( x>x2 || x>x1 ) )。
----------------------------------------------------------------------------------------------------------
代码:
#include<stdio.h>
#include<stdlib.h>
struct p
{
int x,y;
}p[1005],re[1005];
int qcmp(const void *a,const void *b)
{
if( a>b ) return 1;
else if( a<b ) return -1;
return 0;
}
int main()
{
int t,n,m,i,j,h,k,count,x,y;
scanf("%d",&t);
while( t-- )
{
scanf("%d%d",&n,&m);
for(count=h=i=0;i<m;i++)
scanf("%d%d",&p[i].x,&p[i].y);
qsort(p,m,sizeof(p[0]),qcmp);
for(x=y=-1,i=0;i<m;i++)
for(j=i;j<m;j++)
if( ( p[i].y == p[j].y )
&& ( p[i].x>x || p[j].x>y )
&& ( p[i].x>y || p[j].x>x ) )
{
x=p[i].x;
y=p[j].x;
if( x == y )
count++;
else
count+=2;
}
printf("%d\n",count);
}
return 0;
}