【解題報告】 洛谷 P3492 [POI2009]TAB-Arrays
【解題報告】 洛谷 P3492 [POI2009]TAB-Arrays
這題是我隨機跳題的時候跳到的。寫完這道題之後,順便看了一下題解,發現只有一篇題解,所以就在這裏順便寫一個解題報告了。
首先當然是題目鏈接
順便貼一下csdn的網址
題目描述
給出兩個n*m的矩陣,保證每個矩陣內元素互不相同且權值均在[-10^6,10^6]之間,請能否把其中一個矩陣通過若幹次交換兩行或者交換兩列的操作變成另外一個矩陣。
輸入輸出格式
輸入格式
第一行是一個整數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)
上面那個方法可行的原因就在於:他們都可以變成一個排好序的數組,只要比較兩個排好序的數組是否相等就可以了。而矩陣看起來不能這麽幹的原因就在於:你好像不能給他排序。
那麽,我們回來我們現在這道題。我們通過仔細地思考,不難發現一個有趣的事實:無論是交換兩行,還是交換兩列,交換前後,本來在同一列的元素依然在同一列,本來在同一行的元素依然在同一行。只不過,經過交換之後,同一行或則同一列的元素的相對位置會改變而已。
所以,我們有這麽一個想法:首先,把最小的一個元素放在左上角,然後分別以第一行為關鍵字和第一列為關鍵字對它進行排序。然後比較兩個排好序之後的矩陣是否相等。
具體做法如下:
具體做法
- 把矩陣中最小的一個數通過變換放到矩陣的最左上角。(對兩個矩陣都進行同樣的操作,下面也是一樣)
- 以矩陣的第一行為關鍵字,利用變換,使得第一行的數字有序(從大到小,或者從小到大)
- 以矩陣的第一列為關鍵字,利用變換,使得第一列的數字有序(從大到小,或者從小到大)
- 比較兩個矩陣經過上述兩個變換之後是否完全相等。
下面就是我的代碼。
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