请教一个关于“蛇形矩阵”的算法

zhouhong0801 2007-08-25 09:22:57
生成一个按蛇形方式排列自然数1,2,3,4,5,……,N2的 (1<N≤10)阶方阵。
例如:
输入: N=4 N=7
输出: 1 3 4 10 1 3 4 10 11 21 22
2 5 9 11 2 5 9 12 20 23 34
6 8 12 15 6 8 13 19 24 33 35
7 13 14 16 7 14 18 25 32 36 43
15 17 26 31 37 42 44
16 27 30 38 41 45 48
28 29 39 40 46 47 49

请高手指教一下,在循环中应该怎样确定输出数组中每个元素的值,谢谢!
...全文
1124 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
Vitin 2007-08-26
  • 打赏
  • 举报
回复
linfengc的思路和yajia2000的程序很精彩,学习。

所以解决这类问题的方法至少有两种:
一种是将题义描述的过程用程序表现出来,动态地生成结果。
另一种是推导出其中的规律,程序不再局限于题义描述的过程,而是静态地表达这些规律。
这两种方法各擅所长。相比较而言,后一种难度大一些,运行效率高一些,因为它是对规律的抽象,而非对过程的抽象。
Vitin 2007-08-26
  • 打赏
  • 举报
回复
step表示各个状态下的x,y步进量。
如state==0表示向下走,此时x 不变,y+=1,所以step[0][0] = 0, step[0][1] = 1;
再如state==1表示向右上走,此时x+=1,y+= -1,所以step[1][0]=1, step[1][1] = -1。
以此类推。

方向判断是四个状态的跳转。例如:
当state==0(向下走)时,如果当前位置在最左边(x==0),那么下一步开始向右上走(state=1),否则下一步开始向左下走(state=3,此时位置是在最右边)
再如,state=1(向右上走),只有触边时(最右或最上)才需要调整状态。调整的规则是:当在最右边(x==number-1)时,下一步开始向下走(state=0),否则下一步开始向右走(state=2,此时位置是在最上边且不再最右边,即右上角应向下而不能向右走)。
以此类推。

这些规则是根据题义得出的。当然,如果能推导出数学公式,是最好的了,呵呵。
zhouhong0801 2007-08-26
  • 打赏
  • 举报
回复
To Vitin(卫亭) :

我不明白你的数组step[4][2]是根据什么定义的?我估计是跟你的那个switch语句判断的方向有关,能否具体解释一下呢?
还有就是你的方向判断,是根据什么判断呢?这样看,有点不太懂。

还是想请高手解释清楚一点,我比较笨,呵呵。谢谢了!
yajia2000 2007-08-26
  • 打赏
  • 举报
回复
楼上的算法确实好,程序写出了也很简单。
#include <iostream>
#define MAX 16
using namespace std;
void main()
{
int c,c1,i,j,n,count,count1,array[MAX][MAX];
cout<<"请输入矩阵阶(0-15范围):";
cin>>n;
for(int a=0;a<=n+1;a++) //初始化数组
for(int b=0;b<=n+1;b++)
array[a][b]=0;
array[1][1]=1;
array[n][n]=n*n;
for(c=0,count=0,i=2;i<=n;i++,c++) //初始化第一列
if(c%2==0)
{
array[i][1]=array[i-1][1]+1;
count++;
}
else
array[i][1]=array[i-1][1]+count*4;
for(c1=0,count1=0,j=n-1;j>1;j--,c1++) //初始化最后一行,c用来计算列值变化
if(c1%2==0)
{
array[n][j]=array[n][j+1]-(count1*4+2);
count1++;
}
else
array[n][j]=array[n][j+1]-1;
for(i=n-1;i>=1;i--) //列1和行n已经赋值,现计算之外的部分即可
for(j=2;j<=n;j++)
if((i+j)%2==0)
array[i][j]=array[i+1][j-1]-1;
else
array[i][j]=array[i+1][j-1]+1;
for(i=1;i<=n;i++) //输出结果
{
for(j=1;j<=n;j++)
cout<<array[i][j]<<'\t';
cout<<endl<<endl;
}
}
zhouhong0801 2007-08-26
  • 打赏
  • 举报
回复
向高手学习!

我还没时间很很很认真的看ls各位的精彩分析,不过很感谢大家的帮忙!

不过,linfengc的思路我看了一下,还是没搞清楚行之间的规律,我尝试用N=7的输出结果来分析,好像和linfengc的分析不太一样。
其实,我个人觉得Vitin的分析方法应该是解决这个问题,在算法上的最优化的方法,但是这个算法分析太复杂,不易懂;linfengc的方法只要推理得当,找出其中的规律,应该是最简单的了。

以上是个人愚见,如果有不同意见,请大家指教!
Phoenix_ 2007-08-25
  • 打赏
  • 举报
回复
楼上的方案貌似不错
linfengc 2007-08-25
  • 打赏
  • 举报
回复
我认为这个可以最优了,呼呼
linfengc 2007-08-25
  • 打赏
  • 举报
回复
我总结出来了一个十分有趣的规律,
这样根据算法写出程序来应该很简单了
大家看,每行,每列的 增量 规律
1 3 4 10 11 21 22(原数据)
+ 2 1 6 1 10 1 14 1。。。(增量1和4)
3 1 3 8 3 12。。。 (增量3和4)
2 5 6 5 10 5。。。 (增量5和4)
7 4 7 8 7 12。。。 (增量7和4)
。 。 。 。 。 。
。 。 。 。 。 。
第一个数必然是1,那么一行一列的数就先确定好了
再根据怎两规律,就能写出没一行了。

1 + 1
2 + 4
6 + 1
7 + 4 * 2
15 + 1
16 + 4 * 3
28 + 1
29 + 4 * 4
linfengc 2007-08-25
  • 打赏
  • 举报
回复
牛人啊,这么快就搞出来了
lin_style 2007-08-25
  • 打赏
  • 举报
回复
让我想起了迷宫里的方向判断。。不过这个不是最优

应该总结个公式出来
Vitin 2007-08-25
  • 打赏
  • 举报
回复
#include <iostream>

int main()
{
using std::cout;
using std::cin;
using std::endl;

int number;
cout << "Enter a positive integer: ";
cin >> number;

int* arr = new int[number*number];

const int step[4][2] = { 0,1, 1,-1, 1,0, -1,1 };

arr[0] = 1;

for (int x =0,y = 0, state = 0, cur = 2; cur <= number*number; )
{
x += step[state][0];
y += step[state][1];

arr[y*number + x] = cur++;

switch (state)
{
case 0: // down
state = x == 0 ? 1 : 3;
break;
case 1: // right-up
if (y == 0 || x == number-1)
{
state = x == number-1 ? 0 : 2;
}
break;
case 2: // right
state = y == 0 ? 3 : 1;
break;
case 3: // left-down
if (x == 0 || y == number-1)
{
state = y == number-1 ? 2 : 0;
}
}
}

for (int y = 0; y < number; y++)
{
for (int x = 0; x < number; x++)
cout << arr[y*number + x] << "\t";
cout << endl;
}

delete [] arr;

system("pause");
}

最重要的是那个switch语句,四种状态之间的跳转。
linfengc 2007-08-25
  • 打赏
  • 举报
回复
好变态奥
Phoenix_ 2007-08-25
  • 打赏
  • 举报
回复
递归之前加入判断及其操作 即可
Phoenix_ 2007-08-25
  • 打赏
  • 举报
回复
用递归
iatsbg 2007-08-25
  • 打赏
  • 举报
回复
有三种方法。
1.找出x行y列的那个数的表达式,难度比较大,但程序写出来很简单。
2.声明一个n*n的数组,然后模拟数的生成方式,向数组填数。填完输出就行了,写起来比较复杂。
3.自己找张纸把10*10的方阵写出来,然后int a[10][10]={1,3,4,10,1,21,22...}。这样写程序不用动脑,而且效率最高。

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧