【解题报告】 洛谷 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代码

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2500;
const int INF=100000000;
struct ary
{
int n[N];
bool operator<(const ary &b)const
{
return n[1]<b.n[1];
}
};
ary a[N],b[N],c[N],d[N];
int main()
{
int test_num;
scanf("%d",&test_num);
while(test_num--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i].n[j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&b[i].n[j]);
int x=0,ma=INF;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i].n[j]<ma)
{
x=j;
ma=a[i].n[j];
}
}
}
for(int i=1;i<=n;i++)
{
int temp=a[i].n[1];
a[i].n[1]=a[i].n[x];
a[i].n[x]=temp;
}
sort(a+1,a+1+n);
ma=INF;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(b[i].n[j]<ma)
{
x=j;
ma=b[i].n[j];
}
}
}
for(int i=1;i<=n;i++)
{
int temp=b[i].n[1];
b[i].n[1]=b[i].n[x];
b[i].n[x]=temp;
}
sort(b+1,b+1+n);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
c[i].n[j]=a[j].n[i];
d[i].n[j]=b[j].n[i];
}
}
sort(c+1,c+1+m);
sort(d+1,d+1+m);
int flag=0;
for(int i=1;i<=m;i++)
{
if(flag) break;
for(int j=1;j<=n;j++)
{
if(c[i].n[j]!=d[i].n[j])
{
flag=1;
break;
}
}
}
if(flag)
{
printf("NIE\n");
}
else printf("TAK\n");
}
return 0;
}

【解题报告】 洛谷 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. hdu2852 KiKi&#39;s K-Number

    Problem Description For the k-th number, we all should be very familiar with it. Of course,to kiki i ...

  2. JPA学习笔记(13)——查询缓存

    使用hibernate的查询缓存 运行下面代码: String jpql = "FROM User u WHERE u.id = ?"; Query query = entityM ...

  3. Android 信息提示——Toast方式

    Toast用于向用户显示一些帮助/提示.一下列举了5中样式. 一.默认的效果(显示在屏幕的底部) 代码: Toast.makeText(getApplicationContext(), "默 ...

  4. 选择排序(2)——堆排序(heap sort)

    前期概念: 二叉树 完全二叉树 左序遍历 中序遍历 右序遍历 堆 小根堆 大根堆 堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种.可以利用数组的特点 ...

  5. WebView播放H5课件时,锁屏解锁后,页面重新绘制的问题

    难题描述:H5页面播放 ,锁屏,解锁后,重新加载了页面,三星不会出现(onpause onstop ,onresume),但在小米.魅族会调用 onpause onstop ondestroy,onr ...

  6. JSP-Runoob:JSP 异常处理

    ylbtech-JSP-Runoob:JSP 异常处理 1.返回顶部 1. JSP 异常处理 当编写JSP程序的时候,程序员可能会遗漏一些BUG,这些BUG可能会出现在程序的任何地方.JSP代码中通常 ...

  7. [Swift通天遁地]二、表格表单-(2)创建右侧带有索引的UITableView(表单视图)

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  8. phonegap在eclipse上的安装

    1.首先安装好eclipse 2.下载安装好sdk 3.下载安装好adt 4.在这个地方下载好phonegap的包,https://codeload.github.com/phonegap/phone ...

  9. 【转】mysql的数据类型

    转自:http://mrxiong.blog.51cto.com/287318/1651098 一.数值类型 Mysql支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER,SMALL ...

  10. vue-cli 打包优化

    1. 优化打包体积 先上2个图 (上图A是优化前的各个js大小对比视图,下图B是优化后,还未完全优化完成的,不过也可以看得出来对比) 图A是3个压缩文件,包括部分图片和使用的所有js,体积都偏大 图B ...