题目大意:给你一个n*m的矩阵,矩阵中是1到n*m的排列,每次可以翻转一行或翻转一列,给出一个10*n*m内的方案,将其变为按顺序的,或者说不可能。 n<=100,m<=100
这题比较坑,改了一天。。。。
首先一个格子只能翻到四个格子里去,所以先把这种无解判掉
然后想办法把最周围的一圈排好(谁便怎么翻都行),然后剩下的因为四周都不能动了,所以每行每列只能翻偶数次(就谁便怎么乱翻,但是翻过去的一定还要翻回来,不然最外面一圈就不对了),然后翻不好就无解,翻的好就输出。。。
#include<cmath> #include<cstdio> #include<cstring> #include<cassert> #include<iostream> #include<algorithm> using namespace std; const int maxn=107; int n,m; int a[maxn][maxn]; void init(){ scanf("%d%d",&m,&n); for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) scanf("%d",a[i]+j); } bool check(){ for (int i=1,cnt=0;i<=n;++i) for (int j=1;j<=m;++j) if (++cnt!=a[i][j] && a[i][m-j+1]!=cnt && a[n-i+1][j]!=cnt && a[n-i+1][m-j+1]!=cnt) return 1; return 0; } void C(int x){ int N=n>>1; for (int i=1;i<=N;++i) swap(a[i][x],a[n-i+1][x]); } void R(int x){ int M=m>>1; for (int i=1;i<=M;++i) swap(a[x][i],a[x][m-i+1]); } int op[maxn*maxn*10],w[maxn*maxn*10],tot; void de(char a,int b,char c,int d){ op[++tot]=a; w[tot]=b; op[++tot]=c; w[tot]=d; op[++tot]=a; w[tot]=b; op[++tot]=c; w[tot]=d; } void work(){ if (check()) {puts("IMPOSSIBLE"); return;} tot=0; for (int j=1;j<=m;++j){ if (a[1][j]!=j){ if (a[1][m-j+1]==j) op[++tot]='C',w[tot]=m-j+1,C(m-j+1); if (a[n][m-j+1]==j) op[++tot]='R',w[tot]=n,R(n); if (a[n][j]==j) op[++tot]='C',w[tot]=j,C(j); } } for (int i=1;i<=n;++i){ int now=(i-1)*m+1; if (a[i][1]!=now){ if (a[n-i+1][1]==now) op[++tot]='R',w[tot]=n-i+1,R(n-i+1); if (a[n-i+1][m]==now) op[++tot]='C',w[tot]=m,C(m); if (a[i][m]==now) op[++tot]='R',w[tot]=i,R(i); if (a[1][m]!=m) op[++tot]='C',w[tot]=m,C(m); } } for (int j=1;j<=m;++j){ int i=1,now=(n-i)*m+j; while (a[n-i+1][j]!=now){ de('R',n-i+1,'C',m-j+1); swap(a[n-i+1][m-j+1],a[i][m-j+1]),swap(a[n-i+1][m-j+1],a[n-i+1][j]); } now=(n-i)*m+(m-j+1); if (a[n-i+1][m-j+1]!=now){ op[++tot]='C'; w[tot]=m-j+1; C(m-j+1); } } for (int i=1;i<=n;++i){ int j=1,now=(i-1)*m+(m-j+1); while (a[i][m-j+1]!=now){ de('R',n-i+1,'C',m-j+1); swap(a[n-i+1][m-j+1],a[i][m-j+1]),swap(a[n-i+1][m-j+1],a[n-i+1][j]); } now=(n-i)*m+(m-j+1); if (a[n-i+1][m-j+1]!=now){ op[++tot]='R'; w[tot]=n-i+1; R(n-i+1); } } int N=(n+1)>>1,M=(m+1)>>1; for (int i=1;i<=N;++i) for (int j=1;j<=M;++j){ int now=(i-1)*m+j; if (a[i][j]!=now){ if (a[n-i+1][j]==now){ de('C',j,'R',i); swap(a[i][j],a[i][m-j+1]),swap(a[i][j],a[n-i+1][j]); } if (a[n-i+1][m-j+1]==now){ de('R',n-i+1,'C',m-j+1); swap(a[n-i+1][m-j+1],a[i][m-j+1]),swap(a[n-i+1][m-j+1],a[n-i+1][j]); } if (a[i][m-j+1]==now){ de('R',i,'C',j); swap(a[i][j],a[n-i+1][j]),swap(a[i][j],a[i][m-j+1]); } } now=(n-i)*m+j; while (a[n-i+1][j]!=now){ de('R',n-i+1,'C',m-j+1); swap(a[n-i+1][m-j+1],a[i][m-j+1]),swap(a[n-i+1][m-j+1],a[n-i+1][j]); } now=(n-i)*m+(m-j+1); if (a[n-i+1][m-j+1]!=now){puts("IMPOSSIBLE"); return;} } printf("POSSIBLE %d",tot); for (int i=1;i<=tot;++i) printf(" %c%d",op[i],w[i]); puts(""); } int main(){ int T; scanf("%d",&T); while (T--) init(),work(); return 0; }