OpenJudge NOI 1.8 23:二维数组回形遍历

【题目链接】

OpenJudge NOI 1.8 23:二维数组回形遍历

【题目考点】

1. 二维数组

【解题思路】

解法1:移动焦点

设焦点位置,焦点移动同时输出焦点位置的值。焦点从左上角先后以:右下左上右下左上。。。的形式循环移动遍历。如果焦点移出矩阵范围,或焦点下一次要移动到的位置已经有值,那么就改变焦点移动方向,再取下一个位置。
设方向数组的下标d,方向数组dir[d]表示一种方向,d为0,1,2,3分别对应方向右,下,左,上。d=(d+1)%4即可变为下一个方向。

解法2:递归

递归问题为:从(1,1)位置开始输出row行col列矩阵的外圈元素,然后从(2,2)位置开始输出row-2行col-2列矩阵的外圈元素。
递归出口:矩阵的行或列数量小于1,则结束递归。

【题解代码】

解法1:移动焦点
  • 下标从1开始
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};//方向数组:右下左上 
    int row, col, a[105][105], d = 0;//d:dir数组的下标 
    bool vis[105][105] = {};//vis[i][j]:第i,j位置是否已经输出 
    cin >> row >> col;
    for(int i = 1; i <= row; ++i)
        for(int j = 1; j <= col; ++j)
            cin >> a[i][j];
    int fi = 1, fj = 1, si, sj;//(fi,fj):焦点位置 (si,sj)下一个位置
    for(int k = 1; k <= row*col; ++k)
    {
        cout << a[fi][fj] << endl;
        vis[fi][fj] = true;
        si = fi + dir[d][0], sj = fj + dir[d][1];//设下一个位置(si,sj) 
        if(si < 1 || si > row || sj < 1 || sj > col || vis[si][sj])//如果下一个位置在矩阵外或已经输出 
            d = (d+1)%4;//变为下一个方向
        fi = fi + dir[d][0], fj = fj + dir[d][1];//移动焦点     
    }
    return 0;
}
  • 下标从0开始
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};//右下左上 
    int row, col, a[105][105], d = 0;//d:dir数组的下标 
    bool vis[105][105] = {};//vis[i][j]:第i,j位置是否已经输出 
    cin >> row >> col;
    for(int i = 0; i < row; ++i)
        for(int j = 0; j < col; ++j)
            cin >> a[i][j];
    int fi = 0, fj = 0, si, sj;//(fi,fj):焦点位置 (si,sj)下一个位置
    for(int k = 1; k <= row*col; ++k)
    {
        cout << a[fi][fj] << endl;
        vis[fi][fj] = true;
        si = fi + dir[d][0], sj = fj + dir[d][1];//设下一个位置(si,sj) 
        if(si < 0 || si >= row || sj < 0 || sj >= col || vis[si][sj])//如果下一个位置在矩阵外或已经输出 
            d = (d+1)%4;//变为下一个方向
        fi = fi + dir[d][0], fj = fj + dir[d][1];//移动焦点     
    }
    return 0;
}
解法2:递归
  • 下标从1开始
#include<bits/stdc++.h>
using namespace std;
int a[105][105];
//从(sx,sy)位置开始输出row行col列矩阵的外圈元素 
void solve(int sx, int sy, int row, int col)
{
    if(row < 1 || col < 1)
        return;
    else if(row == 1)//只有一行 
    {
        for(int j = sy; j <= sy+col-1; ++j)
            cout << a[sx][j] << endl;
    }
    else if(col == 1)//只有一列 
    {
        for(int i = sx; i <= sx+row-1; ++i)
            cout << a[i][sy] << endl;
    }
    else//多行多列 
    {
        for(int j = sy; j <= sy+col-2; ++j)
            cout << a[sx][j] << endl;
        for(int i = sx; i <= sx+row-2; ++i)
            cout << a[i][sy+col-1] << endl;
        for(int j = sy+col-1; j >= sy+1; --j)
            cout << a[sx+row-1][j] << endl;
        for(int i = sx+row-1; i >= sx+1; --i)
            cout << a[i][sy] << endl;
    }
    solve(sx+1, sy+1, row-2, col-2);
}
int main()
{
    int row, col;
    cin >> row >> col;
    for(int i = 1; i <= row; ++i)
        for(int j = 1; j <= col; ++j)
            cin >> a[i][j];
    solve(1, 1, row, col);
    return 0;
}
  • 下标从0开始
#include<bits/stdc++.h>
using namespace std;
int a[105][105];
//从(sx,sy)位置开始输出row行col列矩阵的外圈元素 
void solve(int sx, int sy, int row, int col)
{
    if(row < 1 || col < 1)
        return;
    else if(row == 1)//只有一行 
    {
        for(int j = sy; j <= sy+col-1; ++j)
            cout << a[sx][j] << endl;
    }
    else if(col == 1)//只有一列 
    {
        for(int i = sx; i <= sx+row-1; ++i)
            cout << a[i][sy] << endl;
    }
    else//多行多列 
    {
        for(int j = sy; j <= sy+col-2; ++j)
            cout << a[sx][j] << endl;
        for(int i = sx; i <= sx+row-2; ++i)
            cout << a[i][sy+col-1] << endl;
        for(int j = sy+col-1; j >= sy+1; --j)
            cout << a[sx+row-1][j] << endl;
        for(int i = sx+row-1; i >= sx+1; --i)
            cout << a[i][sy] << endl;
    }
    solve(sx+1, sy+1, row-2, col-2);
}
int main()
{
    int row, col;
    cin >> row >> col;
    for(int i = 0; i < row; ++i)
        for(int j = 0; j < col; ++j)
            cin >> a[i][j];
    solve(0, 0, row, col);
    return 0;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值