题目
题意:输入L,C,再输入行为L,列为C大小的矩阵。矩阵元素从左到右 ,从上至下编号按照1……C,C+1……2C,……(L-1)*C……LC为要求的矩阵。问需要最少需要进行多少次行 列变换变换成题意要求的矩阵。
思路:这个题的突破口在从1位置入手,标记1的初始位置x,y。从1所在行x进行列变换,若能模拟变换,交换列位置,改变位置y=1;再对第一列元素模拟变换,若能模拟变换,交换行位置。中间只要有不满足变换条件,直接退出。
有点类似转魔方的感觉,找到突破口就好办了,比赛的时候没想出来。充分感受了矩阵下标的规律,太神奇的解决方法了。
AC代码
#include <bits/stdc++.h>
using namespace std;
int a[310][310];
int main()
{
ios::sync_with_stdio(0);
int L,C,x,y;
cin>>L>>C;
for(int i=1; i<=L; i++)
{
for(int j=1; j<=C; j++)
{
cin>>a[i][j];
if(a[i][j]==1)//x,y标记1的坐标位置
{
x=i;
y=j;
}
}
}
int sum=0;
for(int i=1; i<=C; i++)
{
if(a[x][i]!=i)//进行列变换
{
int flag=0;
for(int j=i+1; j<=C; j++)
{
if(a[x][j]==i)
{
if(i==1)//若变换了1的位置,需要重新标记其纵坐标
{
y=1;
}
sum++;
flag=1;
for(int k=1; k<=L; k++)
{
swap(a[k][i],a[k][j]);
}
}
}
if(flag==0)
{
cout<<"*"<<endl;
return 0;
}
}
}
for(int i=1; i<=L; i++)
{
if(a[i][1]!=(i-1)*C+1)//对第一列进行行变换
{
int flag=0;
for(int j=i+1; j<=L; j++)
{
if(a[j][1]==(i-1)*C+1)
{
sum++;
flag=1;
for(int k=1; k<=C; k++)
{
swap(a[i][k],a[j][k]);
}
}
}
if(flag==0)
{
cout<<"*"<<endl;
return 0;
}
}
}
for(int i=1; i<=L; i++)
{
for(int j=1; j<=C; j++)
{
if(a[i][j]!=(i-1)*C+j)//进行行列变换后仍不符合要求
{
cout<<"*"<<endl;
return 0;
}
}
}
cout<<sum<<endl;
return 0;
}