题目描述:
回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
输入:
输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。
输出:
输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
样例输入
3 3 1 2 3 4 5 6 7 8 9
样例输出
1 4 7 8 9 6 3 2 5
算法:逆时针螺旋取数
(1)先考虑m、n相等的情况
经观察可知,取数取n/2个轮回就可以了,每个轮回四次循环分别取向下、右、上、左的列或行。以第一个轮回为例,第一个轮回先向下取4个取到底,然后向右取3个去到底,再向上取3个到底,最后注意向左取两个不到底,到底会多取一次。做完后i++,进入下一次循环。
代码a:把m、n视为相等即可
#include<stdio.h>
void printNumber(int a[][201],int m,int n);
int main(){
int m,n;
int a[201][201];
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
scanf("%d",&a[i][j]);
}
}
printNumber(a,m,n);
return 0;
}
void printNumber(int a[][201],int m,int n){
int i,j,K;
K=n<m?n:m; //这里的k暂时当作n处理,m==n
for(i=0;i<=n/2;i++){ //这里是小于等于当n=3时我们要做两次的
for(j=i;j<=m-1-i;j++){
printf("%d ",a[j][i]);
}
for(j=i+1;j<=n-1-i;j++){
printf("%d ",a[m-i-1][j]);
}
for(j=m-1-i-1;j>=i;j--){
printf("%d ",a[j][n-1-i]);
}
for(j=n-1-i-1;j>=i+1;j--){
printf("%d ",a[i][j]);
}
}
}
样例:
(2)m、n不相等的时候
我们看到末尾多取了一个4出来
这是为什么呢?
原因是,我们做了两次轮回4被取了两次。
首先我们知道当输入m,n不同时,我们取小的,做小的轮回就够了,比如100行2列,显然我们只需要做1次轮回。
以 3 2为例,如上图,显然我们只需要做一次轮回,但输入3 3呢?我们就需要取两次。这不矛盾了吗?这可咋办呢?
其实我们控制轮回的次数就能达到要求,于是我们令轮回的次数i=0 ; i<(1+k)/2,输入 3 2, k 取小的等于2, (1+k)/2=1,做一次轮回,输入3 3时k=3,这时恰好做了两次轮回。
代码b
void printNumber(int a[][201],int m,int n){
int i,j,k;
k=m<n?m:n;
for(i=0;i<(k+1)/2;i++){ //关键代码
for(j=i;j<=m-1-i;j++){
printf("%d ",a[j][i]);
}
for(j=i+1;j<=n-1-i;j++){
printf("%d ",a[m-i-1][j]);
}
for(j=m-1-i-1;j>=i;j--){
printf("%d ",a[j][n-1-i]);
}
for(j=n-1-i-1;j>=i+1;j--){
printf("%d ",a[i][j]);
}
}
}
我们得到了正确的结果。
但是。。。你以为这就结束了吗?
当我们输入4 3时,看看会发生什么
仔细看,数一数,哎嘿,8后面咋多了个5,这是为撒呢?
我们输入 3 5,再看看
我靠*#@&**,这咋又多了个8
我们以 4 3为例,3 5同理
其实,当我们做第二轮的时候5->8是向下的那一次,然后后面的向右需要从8后面的一个数开始,而我们第二次轮回只看5 8两个数,8后面没数,所以循环不执行,但是向上是可以的,我们向上是从8开始向上取一个数一直到最顶,其实就是取到了5,这就是最后的那个多余的小5子,然后向左取,同样不满足条件。那么现在我们既要保证取到5 和 8,但又不想要多余的5,我们就让向下和向右的去取,向上的时候我们加一个限制,即当次轮回的列数大于1,也就是i<n-1-i(n-1-i是这一轮第几列),同理,向左的时候我们令i<m-1-i。
代码c
void printNumber(int a[][201],int m,int n){
int i,j,k;
k=m<n?m:n;
for(i=0;i<(k+1)/2;i++){
for(j=i;j<=m-1-i;j++){
printf("%d ",a[j][i]);
}
for(j=i+1;j<=n-1-i;j++){
printf("%d ",a[m-i-1][j]);
}
for(j=m-1-i-1;j>=i;j--){
if(i<n-1-i)printf("%d ",a[j][n-1-i]); //关键代码
}
for(j=n-1-i-1;j>=i+1;j--){
if(i<m-1-i) printf("%d ",a[i][j]); //关键代码
}
}
}
当当当当,完成了!
ps:做题记录,先草草保存一下