밀어서 맞추는 격자
시간 제한2초메모리 제한512 MB
주어진 절차에 따라 행과 열을 회전시키는 이동만으로 뒤섞인 격자를 행 우선 순서로 정렬하는 문제다.
문제
빈칸 없이 타일로 채워진 직사각형 격자가 있다. 격자는 행 열이라서 타일이 모두 개이고, 타일에는 부터 까지 서로 다른 정수가 하나씩 적혀 있다.
격자를 바꾸는 방법은 밀기 연산뿐이다. 한 번의 밀기는 한 행 전체를 왼쪽이나 오른쪽으로 몇 칸 밀거나, 한 열 전체를 위나 아래로 몇 칸 민다. 경계 밖으로 밀려난 타일은 반대쪽으로 돌아 들어온다. 예를 들어 격자
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
에서 둘째 열을 아래로 한 칸 밀면 다음과 같다.
0 13 2 3
4 1 6 7
8 5 10 11
12 9 14 15
왼쪽으로 칸 밀기는 오른쪽으로 칸 밀기와 결과가 같고, 위로 칸 밀기는 아래로 칸 밀기와 결과가 같다. 그래서 답에는 오른쪽 밀기와 아래쪽 밀기만 쓴다.
첫째 행에 부터 까지, 둘째 행에 부터 까지, 같은 방식으로 마지막 행에 부터 까지 순서대로 놓인 상태를 완성된 상태라고 한다. 뒤섞인 격자를 완성된 상태로 되돌려라.
입력
첫째 줄에 정수 과 이 주어진다 (). 과 은 모두 짝수다. 다음 개 줄에는 격자의 한 행이 왼쪽부터 차례로 정수 개로 주어진다. 타일 개는 부터 까지의 순열이다.
출력
행은 위에서부터 번부터 번까지, 열은 왼쪽에서부터 번부터 번까지 번호를 매긴다. 한 줄에 연산 하나를 출력한다. 1 i r (, )은 번 행을 오른쪽으로 칸 밀고, 2 j d (, )는 번 열을 아래로 칸 민다. 번 행 번 열에 놓여야 하는 타일은 번이다.
같은 격자를 푸는 연산 순서는 여러 가지라서, 답은 아래 절차 하나로 고정한다. 이 절차가 만들어 내는 연산을 그대로 출력한다.
1 i r로 출력되는 연산을 R(i, r), 2 j d로 출력되는 연산을 C(j, d)라고 쓴다. , 일 때 TURN(i, j, a, b)는 다음 네 연산을 이 순서로 뜻한다.
R(i, a)
C(j, b)
R(i, M-a)
C(j, N-b)
TURN(i, j, a, b)는 타일 세 개만 돌리고 나머지 타일은 원래 자리에 그대로 둔다. 번 행 번 열의 타일이 번 행 번 열로, 번 행 번 열의 타일이 번 행 번 열로, 번 행 번 열의 타일이 번 행 번 열로 간다. 여기서 행 번호와 열 번호는 순환하므로 번 행은 번 행, 번 열은 번 열을 뜻한다.
절차는 작업 격자 하나를 들고 진행한다. 작업 격자는 입력 격자로 시작하고, 연산을 출력할 때마다 그 연산을 작업 격자에 바로 적용한다. 그래서 뒤의 단계는 갱신된 격자를 읽는다.
1단계. 에 대해, 각 안에서 에 대해 다음을 한다. 이라 하고, 작업 격자에서 가 놓인 칸을 번 행 번 열이라고 하자.
- 이고 이면 아무것도 출력하지 않는다.
- 그렇지 않고 이면
TURN(i, j, (j-y) mod M, N-1)을 출력한다. - 그 외에는 이다. 를
(j-y) mod M이라 하자. 이면R(x, d)를 출력한다. 이어서TURN(x, j, M-1, x-i)를 출력한다.
2단계. 이제 작업 격자의 마지막 행에는 부터 까지가 어떤 순서로든 놓여 있다. 번 행 번 열의 타일을 라 하고, 로 정의되는 의 순열을 라고 하자. 가 홀순열이면 R(N, 1)을 출력한다.
3단계. 에 대해 다음을 한다. 이라 하고, 번 행에서 가 놓인 열을 라고 하자. 이면 아무것도 출력하지 않는다. 그렇지 않으면 , 이면서 번 행 번 열의 타일이 이 아닌 가장 작은 열 번호를 라고 하자. 그리고 C(t, 1), R(1, (j-t) mod M), TURN(N, j, (j-y) mod M, N-1), R(1, (t-j) mod M), C(t, N-1)을 이 순서로 출력한다.
출력한 연산의 개수를 라고 하자. 첫째 줄에 를 출력하고, 다음 개 줄에 출력한 순서대로 연산을 한 줄에 하나씩 출력한다. 이 절차는 언제나 완성된 상태에 도달하며 연산을 개보다 많이 만들지 않는다. 주어진 격자가 이미 완성된 상태이면 는 이고 출력은 0 한 줄뿐이다.