• BZOJ 1142: [POI2009]Tab


    1142: [POI2009]Tab

    Time Limit: 40 Sec  Memory Limit: 162 MB
    Submit: 213  Solved: 80
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

      每组数据输出“TAK”/“NIE”表示能/不能.

    Sample Input

    2
    4 3
    1 2 3
    4 5 6
    7 8 9
    10 11 12
    11 10 12
    8 7 9
    5 4 6
    2 1 3
    2 2
    1 2
    3 4
    5 6
    7 8

    Sample Output

    TAK
    NIE

    HINT

     

    Source

    [Submit][Status][Discuss]

    分析

    对一个矩阵交换两行的时候,显然行内元素没有发生变化;而交换两列的时候,行内元素也只是变换了顺序而已。所以得出——不论对矩阵进行什么样的变换,原本在一行内的元素现在还在一行,原本在一列的元素现在还在一列。而对于两个矩阵,如果它们每行的元素相同,定能通过若干次对列的交换使得其行内元素顺序也相同;显然列也具有相同的性质。

    由此得出,我们只需要分析两个矩阵的行列是否满足元素相同即可。当然,这个问题的做法不一,或排序,或哈希。因为题目满足元素大小在-1000000到1000000之间,且一个矩阵内不存在相同元素,所以不妨直接用数组记录每个元素在A矩阵中出现的位置。假如一个元素在A矩阵的(a,b)位置出现,在B矩阵的(c,d)位置出现,我们就认为A的a行和B的c行是匹配的,A的b列和B的d列是匹配的。如果出现了一行匹配两行,就是非法的。这样就能做到稳定的O(N*M + 1000000),显然可以过掉了。另外,最好加上读入优化,如果想上榜的话。

    代码

     1 #include <bits/stdc++.h>
     2 
     3 #define N 1005
     4 #define M 1000000
     5 #define K 2000005
     6 
     7 int n, m;
     8 int a[N][N];
     9 int b[N][N];
    10 int posX[K];
    11 int posY[K];
    12 int matchX[N];
    13 int matchY[N];
    14 
    15 signed main(void)
    16 {
    17     int cas; scanf("%d", &cas);
    18     
    19     while (cas--)
    20     {
    21         scanf("%d%d", &n, &m);
    22         
    23         for (int i = 1; i <= n; ++i)
    24             for (int j = 1; j <= m; ++j)
    25                 scanf("%d", &a[i][j]), a[i][j] += M;
    26         
    27         for (int i = 1; i <= n; ++i)
    28             for (int j = 1; j <= m; ++j)
    29                 scanf("%d", &b[i][j]), b[i][j] += M;
    30                 
    31         memset(posX, 0, sizeof(posX));
    32         memset(posY, 0, sizeof(posY));
    33         
    34         for (int i = 1; i <= n; ++i)
    35             for (int j = 1; j <= m; ++j)
    36                 posX[a[i][j]] = i, posY[a[i][j]] = j;
    37                 
    38         bool answer = true;
    39         
    40         memset(matchX, 0, sizeof(matchX));
    41         memset(matchY, 0, sizeof(matchY));
    42                 
    43         for (int i = 1; i <= n; ++i)
    44             for (int j = 1; j <= m; ++j) {
    45                 const int v = b[i][j];
    46                 
    47                 if (!posX[v])
    48                     { answer = false; break; }
    49                 else if (matchX[i] && matchX[i] != posX[v])
    50                     { answer = false; break; }
    51                 else matchX[i] = posX[v];
    52                 
    53                 if (!posY[v])
    54                     { answer = false; break; }
    55                 else if (matchY[j] && matchY[j] != posY[v])
    56                     { answer = false; break; }
    57                 else matchY[j] = posY[v];
    58             }
    59             
    60         puts(answer ? "TAK" : "NIE");
    61     }
    62 }
    BZOJ_1142.cpp

    @Author: YouSiki

  • 相关阅读:
    POJ 最小球覆盖 模拟退火
    POJ 1379 模拟退火
    PythonTip(2)
    PythonTip(1)
    LA 3353 最优巴士线路设计
    LA 4254 贪心
    判断分析
    因子分析——因子得分
    因子分析——应用
    因子分析——因子旋转
  • 原文地址:https://www.cnblogs.com/yousiki/p/6058352.html
Copyright © 2020-2023  润新知