XTU—OJ 1258矩阵

矩阵

题目描述

编写一个程序,将1~n2按行依次填入n×n的矩阵,执行若干条行或者列的循环移动的指令,再将数字按行依次取出。

指令如下:

指令含义
L x yx行循环左移y次
R x yx行循环右移y次
U x yx列循环上移y次
D x yx列循环下移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;
}

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值