让我嘚瑟一下,这题写的比井同学快一点2333[傲娇脸]
嗯,拿到题目的时候本来想用python写的,毕竟可以动态地分配二维数组,但是想想题目限制只有150ms果断放弃了,拿起我的C++呀嘿哟嘿哟~~~
老身是用偏数学的方法计算出要输出的矩阵的规律,不是固定地存储哟~也就是说我压根没用上二维数组
-----------------------------------------啦啦啦,我是题目的分割线-----------------------------------------
题目:
本题要求将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为m行n列,满足条件:m*n等于N;m>=n;且m-n取所有可能值中的最小值。
输入格式:
输入在第1行中给出一个正整数N,第2行给出N个待填充的正整数。所有数字不超过104,相邻数字以空格分隔。
输出格式:
输出螺旋矩阵。每行n个数字,共m行。相邻数字以1个空格分隔,行末不得有多余空格。
输入样例:12 37 76 20 98 76 42 53 95 60 81 58 93输出样例:
98 95 93 42 37 81 53 20 76 58 60 76
---------------------------------------啦啦啦,我是思路的分割线-------------------------------------------
思路:
首先要对所有的数(存在num数组中)进行递减的排序嘛,然后这里偷了个懒直接用<stdlib.h>头文件里面的qsort函数了。。。
然后我的想法是:有一个矩阵的框架,m行n列,在矩阵的对应单元格位置放置相应的数据,那么只要找到数据在num数组中的位置就可以直接输出矩阵啦~
那么要怎么找到矩阵的(x,y)点所需要的数据在num数组中的位置呢?(注:x和y表示坐标)
举个例子:
num是已经排好顺序的20-1的数值,我们需要把它存储在一个5*4的矩阵中
就比如说我们要找到(3,4)点要输出的数字,首先我们可以确定的是这是一个5*4的矩阵,那么(3,4)是在矩阵的第二圈中,矩阵的第i圈有多少个数字呢?根据计算,第i圈有2*(m+n)-4-8*(i-1)个数字,那么我们还要知道(3,4)点是第二圈的第几个数字,这个我选择用while遍历一圈(就是沿着第二圈以->向右->向下->向左->向上的方向跑一圈看哪个坐标吻合) 然后记录步数就能算出该点是第二圈的第4个数字,然后第二圈外的所有圈的步数+第二圈内的步数=num中的索引值,我们可以在num数组中找到这个索引对应的值是3;
然后输出就好啦~
-----------------------------------------恭敬地附上本渣渣的代码--------------------------------------------
#include<iostream>
#include<stdlib.h>
#include<math.h>
using namespace std;
int cmp(const void* a, const void*b)
{
//从大到小排序
return *(int*)b - *(int*)a;
}
int circle(int i, int M, int N)
{
//第i圈有多少个数
return 2 * (M + N) - 4 - (i - 1) * 8;
}
int outside(int i, int M, int N)
{
//第i圈外共有多少个数
int temp = 1;
int sum = 0;
for (temp; temp<i; temp++)
{
sum = sum + circle(temp, M, N);
}
return sum;
}
int inside(int i, int x, int y, int M, int N)
{
//第i-1圈的终止点到第i圈的(x,y)点共有多少个数
//i圈左上边界限制为i
int limitx = N - i + 1;//i圈右下边界限制
int limity = M - i + 1;
int startx = i;//从i圈起始点开始跑一圈
int starty = i;
int count = 1;//因为从起始点开始跑,所以从1计数
while ((startx != x || starty != y) && startx<limitx)
{
//向右跑
startx++;
count++;
}
if (startx == x&&starty == y)return count;
while ((startx != x || starty != y) && starty<limity)
{
//向下跑
starty++;
count++;
}
if (startx == x&&starty == y)return count;
while ((startx != x || starty != y) && startx>i)
{
//向左跑
startx--;
count++;
}
if (startx == x&&starty == y)return count;
while ((startx != x || starty != y) && starty>i)
{
//向上跑
starty--;
count++;
}
if (startx == x&&starty == y)return count;
return 0;//没找到,一般不可能
}
int ind(int x, int y, int M, int N)
{
//根据坐标返回num中的数
//判断(x,y)点位于第几圈
int i, j;
int cir;
if (x>(N + 1) / 2) i = N - x + 1;
else i = x;
if (y>(M + 1) / 2) j = M - y + 1;
else j = y;
if (i <= j) cir = i;
else cir = j;
return outside(cir, M, N) + inside(cir, x, y, M, N);
}
int main()
{
int N, m, n;
int num[10000];//数字
cin >> N;
int i = 0;
for (i; i<N; i++)
{
cin >> num[i];
}
//求矩阵边界
i = (int)sqrt(N);
while (N%i != 0)i--;
m = N / i;
n = i;
//排序
qsort(num, N, sizeof(int), cmp);
int x, y;
for (y = 1; y <= m; y++)
{
int in;
for (x = 1; x<n; x++)
{
in = ind(x, y, m, n);
cout<<num[in-1]<<' ';
}
in = ind(x, y, m, n);
cout<<num[in - 1]<<endl;
}
system("pause");
return 0;
}
---------------------------------------啦啦啦,我是题外话的分割线----------------------------------------
噗噗噗,写博客写到一半发现井同学把bug调出来了,蓝瘦QAQ,等她更完博再附上大佬的链接,毕竟我还是只渣渣~
井同学的博客:点击打开链接