zoukankan      html  css  js  c++  java
  • Matrix

    Problem G: Matrix

    Time Limit: 2 Sec   Memory Limit: 128 MB
    Submit: 80   Solved: 11

    Description

    To efficient calculate the multiplication of a sparse matrix is very useful in industrial filed. Let’s consider
    this problem:
    A is an N*N matrix which only contains 0 or 1. And we want to know the result of AA T.
    Formally, we define B = AA T, Aij is equal to 1 or 0, and we know the number of 1 in matrix A is M
    and your task is to calculate B.

     

    Input

    The input contains several test cases. The first line of input contains a integer C indicating the number
    of the cases.
    For each test case, the first line contains two integer N and M.
    and each of next M lines contains two integer X and Y , which means Axyis 1.
    N ≤ 100000, M ≤ 1000, C ≤ 10

     

    Output

    For each test case, it should have a integer W indicating how many element in Matrix B isn’t zero in one
    line.

     

    Sample Input

    25 31 02 13 33 30 01 02 0

    Sample Output

    39

    HINT

     

    A Tmeans the Transpose of matrix A, for more details, A Tij= Aji.

    eg:

    if Matrix A is:

    123

    456

    789

    then the matrix ATis

    147

    258

    369

    思路:这个题真是做了好久,虽然不是很难,但想法的不同的确会影响做题的结果。
    还有就是开始的时候题目数据有点水,后来改了数据就没能通过,又做了好久才搞出来。
    我把这个过程的经历都说一下:
    题目的意思就是求一个矩阵(元素为1或0)乘以它的转置矩阵,求结果矩阵的元素有多少个不为0,因为数据比较大(100000),直接用数组保持是不现实的,并且也不能运算。开始想到一种方法,实质上b[i][j]=a矩阵的第i行*第j行,而由矩阵的乘法

    b[i][j]=a[i][k]*a'[k][j]+...
    也就是说k值相等的情况下,如果a[i][k]与a'[k][j]都为1,那么b[i][j]一定不为0
    例如
    原矩阵   0 0          0 0 矩阵逆
                 1 0          0 1
                 2 1          1 2
    k值相等,可以看出是0或1,当为0时,可以得出(0 0)(1 1)这两个元素不为0,当为1时,(2 2)不为0
    但这样会有重复的现象,如

    原矩阵   0 0          0 0 矩阵逆
                 0 1          1 0
                 2 1          1 2
    这样得出的点有(0 0)(0 0)(0 2)(2 2)
    出现了计算重复的点,必须把这些点减去
    于是,出现了下面的代码:
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define MAX 1000
    int x[MAX+10],y[MAX+10];
    int main()
    {
         //freopen("in.txt", "r", stdin);
       //freopen("out.txt", "w", stdout);
    	int num,i,j,n,m,ans;
    	scanf("%d",&num);
    	while(num--)
    	{
    	       scanf("%d%d",&n,&m);
    		   for(i=0;i<m;i++)
                     scanf("%d %d",&x[i],&y[i]);
    		   sort(x,x+m);
    		   sort(y,y+m);
    		   ans=0;
    		   for(i=1;i<m;i++)//减去重复的
               {
    			   if(x[i]==x[i-1])
                        ans--;
               }
    		   for(i=0;i<m;i++)
    			   for(j=0;j<m;j++)
    				   if(y[i]==y[j])
                            ans++;
    		   printf("%d
    ",ans);
    	}
    
    	return 0;
    }
    

    提交的时候是过了,但后来发现还有重复的,如


    原矩阵   3 1          1 3 矩阵逆
                 3 2          2 3
                 5 1          1 5
                 5 2          2 5
    点(3 5)和(5 3)重复了,但不是上面那种形式的重复。
    于是改了数据,于是...这种方法就做不了了。
    下面说另一种思路,只加,但没有重复的
    用MAP做就很简单了。。。。。。。
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<map>
    #include<algorithm>
    using namespace std;
    struct node
    {
        int x,y;
    }p[1010];
    map <int,int> mymap;
    int cmp(node a,node b)
    {
        return a.x<b.x;
    }
    int main()
    {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int t,n,m,i,j,k,u,ans,cont;
        scanf("%d",&t);
        int line[1010];
        while (t--)
        {
            memset(line,0,sizeof(line));
            cont=0;ans=0;
            scanf("%d%d",&n,&m);
            for (i=0;i<m;i++)
                scanf("%d%d",&p[i].x,&p[i].y);
            sort(p,p+m,cmp);
            for(i=1;i<m;i++)
                if(p[i].x!=p[i-1].x)
                    line[++cont]=i;//第i行在line中开始的位置
            for(i=0;i<=cont;i++)//一共有cont行
            {
                mymap.clear();
                for(j=line[i];j<(i==cont?m:line[i+1]);j++)
                    mymap[p[j].y]=1;
                for(k=0;k<=cont;k++)
                    for(u=line[k];u<(k==cont?m:line[k+1]);u++)
                        if(mymap.find(p[u].y)!=mymap.end())
                        {
                            ans++;
                            break;//不考虑重复的
                        }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    



  • 相关阅读:
    PHPStorm 2018 的安装 汉化 与使用
    aptana怎么显示空格 tab和回车等
    学习linux—— VMware 安装 ubantu 18 如何连接wifi
    [转]MAC系统下Sublime Text3 配置Python3详细教程(亲测有效)
    如何利用sql 读取辅表的最大max 和第二最大max。。。。
    利用PHPExcel导出excel 以及利用js导出excel
    yii2.0如何优化路由
    教女朋友写第一个php,php环境配置
    js 删除数组中的某一个内容
    vue 路由守卫是否携带token
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3184830.html
Copyright © 2011-2022 走看看