【解题报告】 洛谷 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. 完美解决EditText和ScrollView的滚动冲突(上)

    在网上搜了一下EditText和ScrollView的滚动冲突,发现差点儿全部的解决方式都是触摸EditText的时候就将事件交由EditText处理,否则才将事件交由ScrollView处理.这样确 ...

  2. 约瑟夫环问题(猴子选大王)PHP版

    约瑟夫斯问题问题有时候也被描述成猴子选大王问题,题目如下.(最后会贴上约瑟夫问题的来历) 一群猴子排成一圈,按1,2,…,n依次编号. 然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再 ...

  3. HDU 5289 Assignment (二分+区间最值)

    [题目链接]click here~~ [题目大意]: 给出一个数列,问当中存在多少连续子序列,子序列的最大值-最小值<k [思路]:枚举数列左端点.然后二分枚举右端点,用ST算法求区间最值.(或 ...

  4. Codeforces Round #272 (Div. 2) Dreamoon and WiFi 暴力

    B. Dreamoon and WiFi Dreamoon is standing at the position 0 on a number line. Drazil is sending a li ...

  5. Android 自带Base64加密解密

    Android项目引用不到以下两个java类 import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; Android有自己的base ...

  6. 曼哈顿距离(坐标投影距离之和)d(i,j)=|X1-X2|+|Y1-Y2|.

    曼哈顿距离(坐标投影距离之和)d(i,j)=|X1-X2|+|Y1-Y2|. 我们可以定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生 ...

  7. JSP页面的跳转及传值

    1.response.sendRedirect("跳转到页面的URL"); 该方法通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,使浏览器显示重定向网页的内容. ...

  8. 【BZOJ 2160】 拉拉队排练

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2160 [算法] 先简化题意 : 给定一个字符串,求最长的k个奇回文子串长度的乘积 先 ...

  9. Redis学习和应用记录(1)--介绍和安装

    Redis是一个开源的分布式缓存框架,它也常被理解为数据结构服务器,因为它包含丰富的数据类型,如strings, hashes, lists, sets, sorted sets, bitmaps a ...

  10. php的session

    来源:http://blog.163.com/lgh_2002/blog/static/4401752620105246517509/ http协议是WEB服务器与客户 端(浏览器)相互通信的协议,它 ...