作业-蒙特卡罗-判断矩阵互逆
蒙特卡罗-判断矩阵互逆
题目描述
给定 \(2\) 个 \(n×n\)矩阵 \(A\) 和 \(B\), 试设计一个判定 \(A\) 和 \(B\) 是否互逆的蒙特卡罗算法, 算法的计算时间应为 \(O(n^2)\). 设计一个蒙特卡罗算法, 对于给定的矩阵 \(A\) 和 \(B\), 判定其是否互逆.
Input:
输入的第一行有 \(1\) 个正整数 \(n\), 表示矩阵 \(A\) 和 \(B\) 为 \(n×n\) 矩阵. 接下来的 \(2n\) 行, 每行有 \(n\) 个实数, 分别表示矩阵 \(A\) 和 \(B\) 中的元素.
Output:
矩阵 \(A\) 和 \(B\) 互逆则输出 YES
, 否则输出 NO
Sample Input:
3
1 2 3
2 2 3
3 3 3
-1 1 0
1 -2 1
0 1 -0.666667
Sample Output:
YES
题解
首先根据矩阵互逆定义知道:
\[AB = I
\]
也就是两个矩阵相乘为单位矩阵, 单位矩阵特点就是对角线元素为 \(1\), 其他未知元素为 \(0\) ; 根据这个特点, 我们设计蒙特卡罗算法, 随机选取矩阵的 \(A\) 的第 \(J\) 行, 随机选取矩阵 \(B\) 的第 \(K\) 列, 对应元素相乘并进行累加 \(ans = A_{J1}\times B_{1k} + A_{J2} \times B_{2k} + ... + A_{JN} \times B_{Nk}\), 如果 \(J==k\), 则表示对角线上元素为 \(1\), 即判断 \(ans\) 是否为 \(1\); 如果 \(J!=K\) , 判断 \(ans\) 是否为 \(0\).
CODE
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
double A[maxn][maxn], B[maxn][maxn];
int main()
{
srand(time(NULL));
int n; cin >> n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++) cin >> A[i][j];
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++) cin >> B[i][j];
}
int flag = 0;
for(int i = 1; i <= n; i++)
{
int J = rand() % n + 1, K = rand() % n + 1; // 蒙特卡罗随机选择
double cur = 0;
for(int j = 1; j <= n; j++)
{
cur += (A[J][j] * B[j][K]);
}
if(J == K)
{
if(cur - 1 <= 1e-6) continue;
else flag = 1;
}
else
{
if(cur <= 1e-6) continue;
else flag = 1;
}
}
if(flag) cout << "NO" << endl;
else cout << "YES" << endl;
return 0;
}