简单的题V

问题描述

wzy 给你了一个 n×n 的 01 矩阵 a,你需要求一下满足 ai,j=ai,k=aj,k=1 的三元组 (i,j,k) 的个数。

注:给定的矩阵一定满足 ai,j=aj,i。同时,(1,2,3),(3,2,1)这种视作同一个三元组,且 i≠j,j≠k,i≠k。

输入格式

第一行输入一个数字 nn,表示矩阵大小。(1≤n≤800)

接来下 n 行,每行一个长度为 n 的 01 串。

输出格式

输出满足条件的三元组数量。


样例输入

4
0011
0011
1101
1110

样例输出

2

运行限制

语言最大运行时间最大运行内存
C++1s256M
C1s256M
Java2s256M
Python33s256M

解题思路

我们需要找到满足条件的三元组 (i, j, k),使得 a[i][j] = a[i][k] = a[j][k] = 1,并且 i, j, k 互不相同。由于矩阵是对称的,a[i][j] = a[j][i],因此我们可以简化问题。
我们可以将问题转化为:对于每一个 i,找到所有满足 a[i][j] = 1 且 a[i][k] = 1 且 a[j][k] = 1 的 j 和 k。
具体步骤如下:
①遍历每一个 i:从 0 到 n-1。
​②找到所有与 i 相连的 j:即 a[i][j] = 1 的 j。
​③对于每一个 j,找到所有与 i 和 j 都相连的 k:即 a[i][k] = 1 且 a[j][k] = 1 的 k。
​④统计满足条件的三元组:注意避免重复计数。
为了避免重复计数,我们可以只考虑 i < j < k 的情况,这样每个三元组只会被计算一次。


应用方法

我们可以使用三重循环来解决问题:
①外层循环遍历 i。
②中层循环遍历 j,且 j > i。
③内层循环遍历 k,且 k > j。
这样,我们只需要检查 a[i][j], a[i][k], a[j][k] 是否都为 1。


代码答案

编译语言:C++(g++17)

#include <bits/stdc++.h> //包含所有标准库头文件,方便使用各种STL函数和数据结构
using namespace std; //使用标准命名空间,避免写std::

int main()
{
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); //取消同步流,提高输入输出效率
  
  int n;
  cin >> n; //读取矩阵的大小n

  vector<vector<int>> a(n, vector<int>(n)); //定义nxn的矩阵a
  for(int i = 0; i < n; ++ i)
  {
    string row;
    cin >> row; //读取每一行的01字符串
    for (int j = 0; j < n; ++j)
    {
      a[i][j] = row[j] - '0'; //将字符转换为数字存入矩阵a
    }
  }

  long long count = 0; // 计数器,用于统计满足条件的三元组数量
  for(int i = 0;i < n;++ i)
  {//枚举第一个节点i
    for(int j = i + 1;j < n;++ j)
    {//枚举第二个节点j,确保j>i以避免重复
      if (a[i][j] == 1)
      {//如果节点i和j相连
        for (int k = j + 1; k < n; ++k)
        {//枚举第三个节点k,确保k>j以避免重复
          if(a[i][k] == 1 && a[j][k] == 1)
          {//如果节点i和k相连,且节点j和k相连
            count++; //满足条件,计数器加1
          }
        }
      }
    }
  }

  cout << count << '\n'; //输出满足条件的三元组数量
  
  return 0;
}

代码的复杂度分析

​1.时间复杂度:
  ①外层循环遍历 i,复杂度为 O(n)。
  ②中层循环遍历 j,复杂度为 O(n)。
  ③内层循环遍历 k,复杂度为 O(n)。
  ④总时间复杂度为 O(n^3)。
  ⑤对于 n = 800,800^3 = 512,000,000,在现代计算机上可以接受。
​2.空间复杂度:
  ①矩阵 a 的大小为 n x n,空间复杂度为 O(n^2)。
  ②其他变量(如 count)的空间复杂度为 O(1)。
  ③总空间复杂度为 O(n^2)。


注意事项

1.​矩阵的对称性:
题目中说明矩阵是对称的,即 a[i][j] = a[j][i],因此无需额外处理对称性。
2.​避免重复计数:
通过限制 i < j < k,可以确保每个三元组只被计算一次。
3.​数据类型:
使用 long long 存储计数器 count,因为三元组数量可能非常大。
(最大为 C(n, 3) = n*(n-1)*(n-2)/6,对于 n = 800,约为 85,000,000)
4.​输入优化:
使用 ios::sync_with_stdio(0), cin.tie(0), cout.tie(0) 取消同步流,提高输入输出效率。


总结

1.​代码功能:
该代码用于统计满足条件的三元组 (i, j, k) 的数量,其中 a[i][j] = a[i][k] = a[j][k] = 1。
2.​实现方法:
通过三重循环枚举所有可能的 i, j, k,并检查是否满足条件。
3.​优化:
通过限制 i < j < k 避免重复计数,同时利用矩阵的对称性简化问题。
4.​适用场景:
适用于 n 较小(如 n ≤ 800)的情况。对于更大的 n,需要进一步优化算法。
5.​改进方向:
如果 n 更大,可以考虑使用位运算或其他优化方法减少时间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值