【解题报告】 洛谷 P3492 [POI2009]TAB-Arrays

这题是我随机跳题的时候跳到的。写完这道题之后,顺便看了一下题解,发现只有一篇题解,所以就在这里顺便写一个解题报告了。

首先当然是题目链接

顺便贴一下csdn的网址

题目描述

给出两个n*m的矩阵,保证每个矩阵内元素互不相同且权值均在[-106,106]之间,请能否把其中一个矩阵通过若干次交换两行或者交换两列的操作变成另外一个矩阵。

输入输出格式

输入格式

第一行是一个整数T,表示有T组数据。

每一组数据的第一行是两个整数n和m,表示两个矩阵的大小是n行m列。接下来2*n行里面,每一行有m个数,前n行是第一个矩阵,后n行是第二个矩阵。话说有一点很奇怪,不知道为什么,题目没有给出数据范围,我还是根据内存空间限制算出我能用多少空间的。

输出格式

对于每一组数据,输出一行。若两个矩阵能够通过变换得到对方,则输出TAK,否则,输出NIE

输入输出样例

输入

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

输出

TAK

NIE

解题思路

我们先想一下另外一个问题:现在给你两个数组,问你:是否能把其中一个数组通过若干次交换两个元素的位置变成另外一个数组。

这个问题有一个简单粗暴的做法。对两个数组各自排序,看排序之后的两个数组是否完全相等即可。如,数组[1,4,3,5,6,7]和数组[4,3,6,1,7,5],他们排序过后都是同样的数组[1,3,4,5,6,7],所以这两个数组就可以通过若干次交换两个元素变成另外一个数组。(因为排序的过程就是不断地交换两个元素的位置,如果两个数组A,B都可以通过交换两个元素的位置变成同一个数组C(也就是这个排序之后的数组),那么其中一个数组A也必然可以变成排序之后的数组C,然后数组C再变成另外一个数组B)

上面那个方法可行的原因就在于:他们都可以变成一个排好序的数组,只要比较两个排好序的数组是否相等就可以了。而矩阵看起来不能这么干的原因就在于:你好像不能给他排序。

那么,我们回来我们现在这道题。我们通过仔细地思考,不难发现一个有趣的事实:无论是交换两行,还是交换两列,交换前后,本来在同一列的元素依然在同一列,本来在同一行的元素依然在同一行。只不过,经过交换之后,同一行或则同一列的元素的相对位置会改变而已。

所以,我们有这么一个想法:首先,把最小的一个元素放在左上角,然后分别以第一行为关键字和第一列为关键字对它进行排序。然后比较两个排好序之后的矩阵是否相等。

具体做法如下:

具体做法

  1. 把矩阵中最小的一个数通过变换放到矩阵的最左上角。(对两个矩阵都进行同样的操作,下面也是一样)
  2. 以矩阵的第一行为关键字,利用变换,使得第一行的数字有序(从大到小,或者从小到大)
  3. 以矩阵的第一列为关键字,利用变换,使得第一列的数字有序(从大到小,或者从小到大)
  4. 比较两个矩阵经过上述两个变换之后是否完全相等。

下面就是我的代码。

AC代码

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int N=2500;
  5. const int INF=100000000;
  6. struct ary
  7. {
  8. int n[N];
  9. bool operator<(const ary &b)const
  10. {
  11. return n[1]<b.n[1];
  12. }
  13. };
  14. ary a[N],b[N],c[N],d[N];
  15. int main()
  16. {
  17. int test_num;
  18. scanf("%d",&test_num);
  19. while(test_num--)
  20. {
  21. int n,m;
  22. scanf("%d%d",&n,&m);
  23. for(int i=1;i<=n;i++)
  24. for(int j=1;j<=m;j++)
  25. scanf("%d",&a[i].n[j]);
  26. for(int i=1;i<=n;i++)
  27. for(int j=1;j<=m;j++)
  28. scanf("%d",&b[i].n[j]);
  29. int x=0,ma=INF;
  30. for(int i=1;i<=n;i++)
  31. {
  32. for(int j=1;j<=m;j++)
  33. {
  34. if(a[i].n[j]<ma)
  35. {
  36. x=j;
  37. ma=a[i].n[j];
  38. }
  39. }
  40. }
  41. for(int i=1;i<=n;i++)
  42. {
  43. int temp=a[i].n[1];
  44. a[i].n[1]=a[i].n[x];
  45. a[i].n[x]=temp;
  46. }
  47. sort(a+1,a+1+n);
  48. ma=INF;
  49. for(int i=1;i<=n;i++)
  50. {
  51. for(int j=1;j<=m;j++)
  52. {
  53. if(b[i].n[j]<ma)
  54. {
  55. x=j;
  56. ma=b[i].n[j];
  57. }
  58. }
  59. }
  60. for(int i=1;i<=n;i++)
  61. {
  62. int temp=b[i].n[1];
  63. b[i].n[1]=b[i].n[x];
  64. b[i].n[x]=temp;
  65. }
  66. sort(b+1,b+1+n);
  67. for(int i=1;i<=m;i++)
  68. {
  69. for(int j=1;j<=n;j++)
  70. {
  71. c[i].n[j]=a[j].n[i];
  72. d[i].n[j]=b[j].n[i];
  73. }
  74. }
  75. sort(c+1,c+1+m);
  76. sort(d+1,d+1+m);
  77. int flag=0;
  78. for(int i=1;i<=m;i++)
  79. {
  80. if(flag) break;
  81. for(int j=1;j<=n;j++)
  82. {
  83. if(c[i].n[j]!=d[i].n[j])
  84. {
  85. flag=1;
  86. break;
  87. }
  88. }
  89. }
  90. if(flag)
  91. {
  92. printf("NIE\n");
  93. }
  94. else printf("TAK\n");
  95. }
  96. return 0;
  97. }

【解题报告】 洛谷 P3492 [POI2009]TAB-Arrays的更多相关文章

  1. 洛谷 P3486 [POI2009]KON-Ticket Inspector

    P3486 [POI2009]KON-Ticket Inspector 题目描述 Byteasar works as a ticket inspector in a Byteotian Nationa ...

  2. 解题笔记-洛谷-P1010 幂次方

    0 题面 题目描述 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+ ...

  3. 解题:洛谷4721 [模板]分治FFT

    题面 这是CDQ入门题,不要被题目名骗了,这核心根本不在不在FFT上啊=.= 因为后面的项的计算依赖于前面的项,不能直接FFT.所以用CDQ的思想,算出前面然后考虑给后面的贡献 #include< ...

  4. 解题:洛谷4314 CPU监控

    题面 线段树·二重标记(什么鬼 用(a,b)标记表示先执行+a操作,然后对b取max,维护历史/当前最大值和历史/当前标记.然后我们发现区间加$x$就是$(x,-inf)$,区间赋$x$就是$(-in ...

  5. 解题:洛谷4178 Tree

    题面 重(新)学点分治中...... 普通的点分治一般这几步: 1.找重心 2.从重心开始DFS,得到信息 3.统计经过重心的路径 4.分别分治几棵子树,继续这个过程 然后是常见的(制杖的我的)一些疑 ...

  6. 解题:洛谷2093 JZPFAR

    题面 初见K-D Tree 其实这样的题(欧几里得距离第$x$近点对)不应该用K-D Tree做,因为会被构造数据卡成$O(n^2)$,随机的另说. 但是并没有找到合适的K-D Tree的题(区域统计 ...

  7. 解题:洛谷 p1858 多人背包

    题面 设$dp[i][j]$表示容量为$i$时的第$j$优解,因为是优解,肯定$dp[i][j]$是随着$j$增大不断递减的,这样的话对于一个新加进来的物品,它只可能从两个容量的转移的前$k$优解中转 ...

  8. 解题:洛谷2633 Count on a tree

    题面 在树上建主席树...... 每个点从父亲那里建过来,最后建出来就是从根到$i$这条链上的主席树,查询的时候一边差分一边查询 ($cmt[u]+cmt[v]-cmt[lca(u,v)]-cmt[a ...

  9. 解题:洛谷2257 YY的GCD

    题面 初见莫比乌斯反演 有一个套路是关于GCD的反演经常设$f(d)=\sum_{gcd(i,j)==d},g(d)=\sum_{d|gcd(i,j)}$,然后推推推 $\sum\limits_{i= ...

随机推荐

  1. 第16章 ASP.NET MVC 日志篇

    本章主要介绍MVC中内置的错误处理.日志以及用来提升性能的监控工具 一.错误处理 当该网站忙于处理HTTP请求时,很多内容都会出错.幸运的是,MVC让错误处理工作变得相对简单了很多,因为MVC应用是运 ...

  2. poj2011

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 17608   Accepted: 765 ...

  3. bzoj4756

    http://www.lydsy.com/JudgeOnline/problem.php?id=4756 水题一枚...但是我写了一个小时...手贱打反查不出来... 就是每次线段树合并,先把自己的儿 ...

  4. Flume Avor Source

    1.cd /usr/local2/flume/conf sudo vim avro.conf: a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Des ...

  5. 0619-dedeCMS数据表

    CMS的层级从前台分主要分为首页--栏目页--内容页,从后台分主要是四张表之间的关系: 1.模型表--dede_channeltype(顶级) 2.栏目表--dede_arctype 3.数据表:分为 ...

  6. JavaScript学习四

    2019-06-01 09:09:23 坚持,加油!!! 函数的学习 <html> <head> <script type="text/javascript&q ...

  7. 普通平衡树代码。。。Treap

    应一些人之邀...发一篇代码 #include <iostream> #include <cstdio> #include <cstdlib> #include & ...

  8. Quartz在服务异常中断或者重启后,不执行之前漏掉的任务,重新运行下一次任务

    Quartz默认重启后会执行之前的任务,所以如果不想执行之前漏掉的任务,需要设置一下两个地方: CRON triggers CronTrigger trigger = TriggerBuilder.n ...

  9. jsp文件就是Servlet,可以在tomcat里进行查看

    D:\apache-tomcat-8.0.21\work\Catalina\localhost\springmvc2\org\apache\jsp\index_jsp.class

  10. day01_12/11/2016_Spring入门PPT

    s1 s2 s3 s4 s5 s6 s7 s8 IOC1 IOC2 入门编写1 入门编写2 入门编写3 入门编写4---心得