现在的位置: 首页 > 综合 > 正文

CERC 13A – Rubik’s Rectangle

2017年10月16日 ⁄ 综合 ⁄ 共 2651字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.