bzoj1142 [POI2009]Tab 乱搞

38 篇文章 0 订阅

Description


 2个n*m矩阵,保证同一个矩阵中元素两两不同。问能否通过若干次交换两行或交换两列把第一个矩阵变成第二个。

第一行正整数T(1≤T≤10)表示数据组数.
每组数据包括:第一行nm(1≤n,m≤1000)2个n行m列的整数矩阵,
元素绝对值均在10^6以内
每组数据输出“TAK”/“NIE”表示能/不能.

Solution


直接判断矩阵A能否变换成矩阵B是比较麻烦的
可以考虑设立一个中间矩阵C,若矩阵A和矩阵B均能变换成矩阵C那么我们可以认为A和B是TAK的
一个可行的方案为将矩阵中最小元素移动到左上角,并将剩下的行按照第一列为关键字排序,剩下的列按照第一行为关键字排序。我们对A和B都进行这样的操作然后比较即可

一开始T了是因为排序写成了n^3的(⊙﹏⊙)b

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const int INF=0x3f3f3f3f;
const int N=1005;

int rc[N][N],rc1[N][N],rc2[N][N];

int read() {
    int x=0,v=1; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x*v;
}

void solve(int n,int m) {
    int x=1,y=1;
    rep(i,1,n) rep(j,1,m) {
        if (rc[i][j]<rc[x][y]) {
            x=i; y=j;
        }
    }
    std:: swap(rc[1],rc[x]);
    rep(i,1,n) std:: swap(rc[i][1],rc[i][y]);
    rep(i,1,n) {
        int tmp=rc[i][1],rec=i;
        rep(j,i+1,n) if (rc[j][1]<tmp) {
            tmp=rc[rec=j][1];
        }
        if (rec!=i) std:: swap(rc[i],rc[rec]);
    }
    rep(i,1,m) {
        int tmp=rc[1][i],rec=i;
        rep(j,i+1,m) if (rc[1][j]<tmp) {
            tmp=rc[1][rec=j];
        }
        if (rec!=i) rep(k,1,n) std:: swap(rc[k][i],rc[k][rec]);
    }
}

int main(void) {
    for (int T=read();T--;) {
        int n=read(),m=read();
        rep(i,1,n) rep(j,1,m) rc[i][j]=read();
        solve(n,m);
        rep(i,1,n) rep(j,1,m) rc1[i][j]=rc[i][j];

        rep(i,1,n) rep(j,1,m) rc[i][j]=read();
        solve(n,m);
        rep(i,1,n) rep(j,1,m) rc2[i][j]=rc[i][j];

        bool flag=true;
        rep(i,1,n) rep(j,1,m) if (rc1[i][j]!=rc2[i][j]) {
            flag=false;
            break;
        }
        if (flag) puts("TAK");
        else puts("NIE");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值