- 螺旋矩阵(25)
时间限制
150 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue
本题要求将给定的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
这个题很有趣的,分几个步骤想好,就没问题了。
First,我们需要将输进去的数字排序。这个解决的办法是用C++的algorithm头文件中的sort函数进行排序,用bool自定义排序规则。这个问题算解决了。
Second,我们需要求出来列和行,他们的要求是行大于等于列,这个问题的解决和51 Nod1283的方法一样,先求出sqrt(N),也就是说从中间往N的方向就开始找。这个也算解决了
Third,就是蛇形填数,这个的解决是参考刘汝佳《算法竞赛入门经典》第二版中的例子,程序3-3。看得懂,理解了,自己能写出来那个程序了,就可以了,我把这个程序也放出来:
#include <iostream>
using namespace std;
const int MAXN = 10;
int a[MAXN][MAXN] = {0};
int main()
{
int n, x, y, tot;
cin >> n;
tot = a[x=0][y=n-1] = 1;
while (tot < n*n)
{
while (x + 1 < n && !a[x + 1][y]){ a[++x][y] = ++tot; }
while (y - 1 >= 0 && !a[x][y - 1]){ a[x][--y] = ++tot; }
while (x - 1 >= 0 && !a[x - 1][y]){ a[--x][y] = ++tot; }
while (y + 1 < n && !a[x][y + 1]){ a[x][++y] = ++tot; }
}
for (x = 0; x < n; ++x)
{
for (y = 0; y < n; ++y)
{
printf("%3d", a[x][y]);
}
printf("\n");
}
return 0;
}
看了很久,有几个地方确实需要好好理解,道行尚浅。首先四个while语句里面的!这个符号用的很简练,判断是否放过数字这个事情也没有重开一个二维数组,也很简练。还有就是,while语句里面都是++x,++tot等等,这种把++放在前面,是不可以变的,不能变为x++的。我试了很久,体会了很久。i++和++i的区别很多考二级的都清楚了。i++,先使用i的值,再自加。++i是先自加再使用i的值。如果使用了x++,那就意味着,你走完这一步,就自动往下走了一步,但到底下一步能不能走,我们还不清楚,一旦不能走,我们还要往回撤一步,需要判断。所以,不可取。这也是刘汝佳在习题后面问的问题我的思考。
只要看懂了,理解了这个程序,解决了这三个小问题,整个问题就可以自然而然的解决了。
说起来,如果不是我提交了18遍才过,我是不会把这个题放出来的,之所以我提交一直错,主要是最后一个测试点。刚开始提示超时,后来又提示段错误,我以为是数组开小了,一直往上开,开到两百多,还不行,我就懵了,搜了一堆,又是说memset的清零速度慢,又是说bool cmp函数里应该是return a > b,我就试了很久,都不成,后来,参照他们的,把数组开的小了点,反而成了。就这样,以后长记性;
放代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
bool cmp(int a,int b)
{
return a>=b;
}
int main()
{
int N, i, j;
int n, m;
scanf("%d",&N);
int b[10000];
for(i=0;i<N;i++)
{
scanf("%d",&b[i]);
}
sort(b,b+N,cmp);
int factor=sqrt(N);
if(factor*factor==N)
{
n=m=factor;
}
else {
for(i=factor+1;i<=N;i++)
{
if(N%i==0)
{
m=i;
n=N/i;
break;
}
}
}
int a[m+5][n+5];
memset(a,0,sizeof(a));
int sum=0;
a[0][0]=b[0];
i=0;j=0;
while(sum<N-1)
{
while(j+1<n&&!a[i][j+1])
{
a[i][++j]=b[++sum];
}
while(i+1<m&&!a[i+1][j])
{
a[++i][j]=b[++sum];
}
while(j-1>=0&&!a[i][j-1])
{
a[i][--j]=b[++sum];
}
while(i-1>=0&&!a[i-1][j])
{
a[--i][j]=b[++sum];
}
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(j!=0)
printf(" ");
printf("%d",a[i][j]);
}
printf("\n");
}
return 0;
}