[构造] aw3732. 矩阵复原(模拟+构造)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[构造] aw3732. 矩阵复原(模拟+构造)相关的知识,希望对你有一定的参考价值。

1. 题目来源

链接:3732. 矩阵复原

2. 题目解析

构造题目,思维具有跳跃性…

又没看清题目,每个数只会出现一次,每行、列的也只会出现一次…

那么针对列而言,可以通过输入中列的首元素确定出其在行中出现的位置,即求得在输入行中的行列所在位置,因为每个数字都是唯一的,所有能够查找出来。且只需要知道列的位置关系即可,假设在第 k 列,那么该列元素就是答案的第 k 列。


比较抽象,看 y总笔记吧:
在这里插入图片描述


有一说一,还是得好好读题。本题比较饶,给出的单行、单列中的元素都是按照原数组给出的,但是各行列的顺序发生了变化。

按这个题解,模拟下第一个样例,非常容易帮助理解。

实际上只需要确定一列、或者一行在最终数组中的位置,剩下的就全部确定了,即列的输入,其实只有一列是有效的,其余的完全可以不必读入。

由列确定行所在位置,由行确定列所在位置。秒啊!


个人理解:

在这里插入图片描述
但是,这个写法实际上和本题写法实际上的是一致的,本题的写法更加精炼。 但需要注意的是,本题数据量可以给的更少,即给出全部行,只给一列,或者给出全部列,只给一行。 但是整个复杂度是不变,所以这个想法也没啥大用哈哈😆。


时间复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( n 2 ) O(n^2) O(n2)


#include <bits/stdc++.h>

using namespace std;

const int N = 505;

int n, m;
int a[N * N];       // 存每个数所在的列号
int res[N][N];

int main() {
    int T; cin >>T; while (T -- ) {
        cin >> n >> m;
        for (int i = 0; i < n; i ++ ) 
            for (int j = 0; j < m; j ++ ) {
                int x; 
                cin >> x;
                a[x] = j;
            }
            
        for (int i = 0; i < m; i ++ ) {             // 读取每一列
            int x;
            cin >> x;                             
            int k = a[x];                           // 每列的第一个数,找到在行中的对应列号
            res[0][k] = x;                          // 每列第一个数都是第 0 行的
            for (int j = 1; j < n; j ++ ) {
                int t;
                cin >> t;
                res[j][k] = t;
            }
        }
        
        for (int i = 0; i < n; i ++ ) {
            for (int j = 0; j < m; j ++ ) 
                cout << res[i][j] << ' ';
            cout << endl;
        }
    }
    
    return 0;
}

只用全部行、一列 确定出整个矩阵。

#include <bits/stdc++.h>

using namespace std;

const int N = 505;

int n, m;
int a[N * N], c[N * N];       // 存每个数所在的列号
int b[N][N], col[N];
int res[N][N];

int main() {
    int T; cin >>T; while (T -- ) {
        cin >> n >> m;
        for (int i = 0; i < n; i ++ ) 
            for (int j = 0; j < m; j ++ ) {
                int x; 
                cin >> x;
                c[x] = i, a[x] = j;         // 行、列
                b[i][j] = x;
            }
        
        // 只读一列
        for (int i = 0; i < n; i ++ ) cin >> col[i];
        
        // 后面 m-1 列读空即可
        for (int i = 1; i < m; i ++ )
            for (int i = 0; i < n; i ++ ) {
                int x;
                cin >> x;
            }
        
        // 通过第一列中的元素出现顺序,得到该元素所在原数组行的位置
        // 元素唯一,确定出这一行的所有元素
        // 将其写到答案数组中
        for (int i = 0; i < n; i ++ ) {
            int x = i;                          // 元素在列中所在位置即为行,在行中所在位置即为列
            int t = c[col[i]];                  // 行中哪一行
            
            // 答案写入,在此可以直接输出。因为列确定行,列是按下标走的,是按第 0,1,2,..,n 行进行确定的
            // for (int i = 0; i < m; i ++ ) res[x][i] = b[t][i];  
            for (int i = 0; i < m; i ++ ) cout << b[t][i] << ' ';
            cout << endl;
        }
        /*
        for (int i = 0; i < n; i ++ ) {
            for (int j = 0; j < m; j ++ ) 
                cout << res[i][j] << ' ';
            cout << endl;
        }
        */
    }
    
    return 0;
}

以上是关于[构造] aw3732. 矩阵复原(模拟+构造)的主要内容,如果未能解决你的问题,请参考以下文章

[构造] aw3762. 二进制矩阵(困难模拟+分类讨论+简化代码+思维)

[构造] aw3679. 素数矩阵(构造+思维)

[构造] aw3730. 寻找序列(模拟+构造)

[构造] aw3731. 序列凑零(模拟+构造)

使用 jest 模拟 AWS.DynamoDB.DocumentClient 的构造函数

[构造] aw3767. 最小的值(贪心+模拟)