CERC 13A - Rubik’s Rectangle

来源:互联网 发布:super 在java中的用途 编辑:程序博客网 时间:2024/06/05 20:55

题目大意:给你一个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;}


0 0