1050 螺旋矩阵 (25 分)
本题要求将给定的 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
===================================================
模拟题。螺旋、回形、蛇形诸如此类的填数字,都是一样的套路。
第一步:确定行m,列n。(要求m - n尽可能的小且 m >= n)
题目给定一个N,把它分解成m * n。判断素数的模板是不是可以拿来用了 ?
int func(int Num){
int i = sqrt((double)Num);
while(i >= 1){
if(Num % i == 0) return i; //拆成功了,直接返回这个值
i--;
}
return 1; //如果Num是素数,拆不了,返回1
}
第二步:填数。
因为填数要按从大到小填,事先排好序。开一个二维数组,行为m,列为n(是的,中括号里写变量,c++11支持)。
初始化二维数组值为-1,并预先填好0,0这个位置。(why?等会就明白)
x是行下标控制竖着走,y是列下标控制横着走。
首先,是横着向右走,x不动y动,我们先判断能不能往右走。
怎么判断?(解题关键点)
一是判断下一步越界了吗,即y + 1 < n吗?
二是判断这个格子之前有没有用过?即等于-1吗?(初始为-1,因为填的数全是正整数)。
如果没有越界且格子没被使用过,填数,继续判断下一步...
往下走,往左,往上走都是同一个逻辑,这里不再赘述。
每一次填数前,都要先判断能不能走,能走则走,不能就换路走。如何换路?请看代码。
===================================================
代码本地编译不过因为编译器标准不支持c++11,请提交至OJ上。
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string.h>
using namespace std;
bool cmp(int a, int b){
return a > b;
}
int func(int Num){
int i = sqrt((double)Num);
while(i >= 1){
if(Num % i == 0) return i;
i--;
}
return 1;
}
int main(){
int Num, m, n, cnt = 0;
cin >> Num;
n = func(Num);
m = Num / n;
vector<int> v(Num);
for(int i = 0; i < Num; i++) scanf("%d", &v[i]);
sort(v.begin(), v.end(), cmp);
int a[m][n];
memset(a, -1, sizeof(a));
a[0][0] = v[0];
int x = 0, y = 0;//x是行下标,控制竖着走。y是列下标,控制横着走
while(cnt < Num-1){
while(y+1 < n && a[x][y+1] == -1) a[x][++y] = v[++cnt];
while(x+1 < m && a[x+1][y] == -1) a[++x][y] = v[++cnt];
while(y-1 >= 0 && a[x][y-1] == -1) a[x][--y] = v[++cnt];
while(x-1 >= 0 && a[x-1][y] == -1) a[--x][y] = v[++cnt];
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
printf("%d", a[i][j]);
if(j != n-1) printf(" ");
}
printf("\n");
}
return 0;
}