codeforces1136C Nastya Is Transposing Matrices 构造

本文介绍了一种通过有限次子方阵转置操作,实现任意矩阵A到矩阵B的转换算法。关键在于发现转置变换路径,即沿副对角线方向交换元素,确保两矩阵在相同路径上的元素一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目传送门 ( ̄︶ ̄)↗ 走你

题目大意:给你一个矩阵,你现在只能选取他其中的子方阵转置,次数不限,求是否能从矩阵A变换到矩阵B


构造变换方法,注意到转置偶数次与不转置时相同。
因为我们可以选择任意的子矩阵,所以我们可以构造如下的方法进行变换

  1. 选取一个子矩阵转置,并转置其一个子矩阵
    在这里插入图片描述 这样变换之后,与原子矩阵只有第n行于n列不同,其余位置由于都转置了两次,所以位置不变

  2. 从子矩阵右下选取,使变换后的子矩阵于原矩阵只有右上和左下不同
    在这里插入图片描述 因为原来第n行与第n列被转置一次,所以第一次转置时恢复原来的位置,但是除第n行与第n列外其余位置均转置了2次,所以再选择一个矩阵还原这些位置。

使用这样的变换方式,由于一直在交换左上和右下,不难看出对于一个元素aij,只能移动到位置anm,其中i+j=n+m,也就是沿着与副对角线平行的方向交换,所以我们只需要判断沿副对角线方向上的元素是否一致即可。
在这里插入图片描述


#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>

#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return

#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;

int N,M;
int A[512][512],B[512][512];
priority_queue<int> Q1;
priority_queue<int> Q2;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin>>N>>M;
    rep(i,1,N+1)
        rep(j,1,M+1)
            cin>>A[i][j];
    rep(i,1,N+1)
        rep(j,1,M+1)
            cin>>B[i][j];

    bool safe=true;
    rep(i,1,M+1){
        int posX=1,posY=i;
        while(posX<=N && posY>0){
            Q1.push(A[posX][posY]);
            Q2.push(B[posX][posY]);
            posX++,posY--;
        }

        int num1,num2;
        while(!Q1.empty()){
            num1=Q1.top();
            num2=Q2.top();
            Q1.pop(),Q2.pop();
            if(num1!=num2){
                safe=false;
                break;
            }
        }
        if(!safe)
            break;
    }
    if(!safe){
        cout<<"NO\n";
        re 0;
    }

    rep(i,1,N+1){
        int posX=i,posY=M;
        while(posX<=N && posY>0){
            Q1.push(A[posX][posY]);
            Q2.push(B[posX][posY]);
            posX++,posY--;
        }

        int num1,num2;
        while(!Q1.empty()){
            num1=Q1.top();
            num2=Q2.top();
            Q1.pop(),Q2.pop();
            if(num1!=num2){
                safe=false;
                break;
            }
        }
        if(!safe)
            break;
    }

    if(safe)
        cout<<"YES\n";
    else
        cout<<"NO\n";

    re 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值