矩阵
题目描述
编写一个程序,将1~n2按行依次填入n×n的矩阵,执行若干条行或者列的循环移动的指令,再将数字按行依次取出。
指令如下:
指令 | 含义 |
---|---|
L x y | x行循环左移y次 |
R x y | x行循环右移y次 |
U x y | x列循环上移y次 |
D x y | x列循环下移y次 |
输入
第一行是一个整数K,表示样例的个数。 每个样例的第一行是两个整数n(1≤n≤10)和m(1≤m≤1000),分别表示矩阵的大小和指令的条数。
以后的m行是m条指令,矩阵的行列按1开始计数,指令满足1≤x≤n,1≤y≤n−1。
输出
每行输出一个样例的结果,数字之间用一个空格隔开,行末无空格。
样例输入
4 3 1 L 1 1 3 1 R 1 1 3 1 U 1 1 3 1 D 1 1
样例输出
2 3 1 4 5 6 7 8 9 3 1 2 4 5 6 7 8 9 4 2 3 7 5 6 1 8 9 7 2 3 1 5 6 4 8 9
这个题目最重要的就是如何实现二维数组循环移动:
颠倒交换法
算法描述:循环左移k位, 先把前面 1 到 k位置的数字首尾交换, 然后再把 k 到 len位置首尾交换, 最后再把 1 到 len下标位置首位交换即可实现。例如1 2 3 4 5 6循环左移两次,我们可以先把1到2的数字交换即 2 1 3 4 5 6这个时候再把后边剩下的数字交换即 2 1 6 5 4 3这个时候再整体颠倒交换即3 4 5 6 1 2 ,可以自己感受下。
解决了循环移动的问题后,将其写成函数,之后分情况调用就行了。
#include<stdio.h>
int str[11][11]={0};
void reverse1(int left,int right,int x){
int i=left,j=right;
while(i<j){
int t = str[x][i];
str[x][i] = str[x][j];
str[x][j] = t;
i++;
j--;
}
}
void reverse2(int left,int right,int x){
int i=left,j=right;
while(i<j){
int t = str[i][x];
str[i][x] = str[j][x];
str[j][x] = t;
i++;
j--;
}
}
int main()
{
int i,k,j;
scanf("%d",&k);
while(k--){
int n,m,flag=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
flag++;
str[i][j]=flag;
}
}
while(m--){
char A;
int x,y;
getchar();
scanf("%c%d%d",&A,&x,&y);
if(A=='L')
{
reverse1(1,y,x);
reverse1(y+1,n,x);
reverse1(1,n,x);
}
if(A=='R')
{
reverse1(1,n-y,x);
reverse1(n-y+1,n,x);
reverse1(1,n,x);
}
if(A=='U')
{
reverse2(1,y,x);
reverse2(y+1,n,x);
reverse2(1,n,x);
}
if(A=='D')
{
reverse2(1,n-y,x);
reverse2(n-y+1,n,x);
reverse2(1,n,x);
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==n&&j==n)
{
printf("%d\n",str[n][n]);
break;
}
printf("%d ",str[i][j]);
}
}
}
return 0;
}