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

鸣谢WangTianYi制作数据

[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

时间: 2024-10-05 16:54:01

BZOJ 1142: [POI2009]Tab的相关文章

BZOJ 1142 [POI2009]Tab 模拟

题意:链接略 方法:模拟 解析: 首先如果您做过高三那么您一定清楚,一个矩阵通过任意行列变换后得到的矩阵满足一种性质:原来在哪一行的元素还在那一行,原来在哪一列的元素还在那一列. 并且行列内部元素可以任意交换. 所以暴力验证即可. 代码附带5K读入优化,怒艹BZOJrnk1 代码: #include<cstdio> #include<cstring> #include<cctype> #include<cstdarg> #include <iostre

BZOJ 1142 POI2009 Tab Hash

题目大意:给定两个矩阵,保证矩阵内所有元素都不相同,求第一个矩阵通过交换行和列是否可以得到第二个矩阵 令每一行的哈希值为这一行的元素排序后的RK哈希值,将行按照哈希值排序 然后把每一列按顺序哈希一下,排个序取RK哈希作为整个矩阵的哈希值 判断两个矩阵的哈希值是否相等即可 由于矩阵中元素不重复所以可以保证第一步的哈希值不会出现重复 然后...我都写完了它告诉我是2B题???? 算了反正POI官网上能过就是了= = #include <cstdio> #include <cstring>

BZOJ 1115: [POI2009]石子游戏Kam

1115: [POI2009]石子游戏Kam Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 924  Solved: 574[Submit][Status][Discuss] Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数.两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏.问先手是否必胜. Input 第一行u表示数据组数.对于每组数据,第一行

BZOJ 1137: [POI2009]Wsp 岛屿 半平面交

1137: [POI2009]Wsp 岛屿 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 165  Solved: 78[Submit][Status][Discuss] Description Byteotia岛屿是一个凸多边形.城市全都在海岸上.按顺时针编号1到n.任意两个城市之间都有一条笔直的道路相连.道路相交处可以自由穿行.有一些道路被游击队控制了,不能走,但是可以经过这条道路与未被控制的道路的交点.问

bzoj 1138: [POI2009]Baj 最短回文路 dp优化

1138: [POI2009]Baj 最短回文路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 161  Solved: 48[Submit][Status] Description N个点用M条有向边连接,每条边标有一个小写字母. 对于一个长度为D的顶点序列,回答每对相邻顶点Si到Si+1的最短回文路径. 如果没有,输出-1. 如果有,输出最短长度以及这个字符串. Input 第一行正整数N和M ( 2 ≤ N ≤ 400 , 1 ≤ M ≤

bzoj 1133: [POI2009]Kon dp

1133: [POI2009]Kon Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 242  Solved: 81[Submit][Status][Discuss] Description 火车沿途有N个车站,告诉你从每一站到每一站的人数,现在查票员只能查K次票,每次查票可以控制目前在车上的所有乘客的车票.求一个查票方案,使得控制的不同的乘客尽量多. (显然对同一个乘客查票多次是没有意义的,只算一次) Input 第一行正整数 N K (1≤K<

bzoj 1115: [POI2009]石子游戏Kam -- 博弈论

1115: [POI2009]石子游戏Kam Time Limit: 10 Sec  Memory Limit: 162 MB Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数.两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏.问先手是否必胜. Input 第一行u表示数据组数.对于每组数据,第一行N表示石子堆数,第二行N个数ai表示第i堆石子的个数(a1<=a2<=……<=an). 1

[BZOJ 1115] [POI2009] 石子游戏Kam 【阶梯博弈】

题目链接:BZOJ - 1115 题目分析 首先看一下阶梯博弈: 阶梯博弈是指:初始有 n 堆石子,每次可以从任意的第 i 堆拿若干石子放到第 i - 1 堆.最终不能操作的人失败. 解法:将奇数位的石子堆做最基本的 NIM 就可以了. WHY:对奇数位做 NIM 的必胜者总是可以胜利,因为如果从奇数位拿石子到偶数位,就相当于把这些石子拿走了,就是 NIM :如果必败者从偶数位将石子拿到奇数位,必胜者总是可以将这些石子再向前移一个位置,就又放到了偶数位,这样一直移动的话,最终会是必胜者将这些石子

BZOJ 1138 POI2009 Baj 最短回文路 BFS

+题目大意:给定一张有向图,每个点有一个字符,多次求两点的最短回文路 据说这道题第一次做的人都会T? 一开始的思路是这样的:令fx,y表示从点x走到点y的最短回文路径,转移fx,y=min{fz,w+2|x?c?>z,w?c?>y} 然后广搜,果断T了= = 冗余的转移太多了-- 正解是这样的: 令gx,y,c表示从点x走到点y,除了最后一条边之外是回文路径且最后一条边的字符为c的最短路 然后转移是这样的: gx,y,c=min{fx,z+1|z?c?>y} fx,y=min{gz,y,