我需要为Pascal编写一个程序,它以如下的螺旋形式生成数组:
(7) (8) (9) (10)
(6) (1) (2) (11)
(5) (4) (3) (12)
(16)(15)(14)(13)
从1开始并继续到36但这不是那么重要。
经过3天的思考,我不知道如何实现这个目标。
问题不在于语言语法或数组,它只是在算法中。
您能用任何编程语言帮助我处理任何想法,链接,伪代码或程序代码吗?
答案 0 :(得分:1)
考虑将nxn矩阵拆分为2x2,4x4,... nxn的同心子矩阵。在你的情况下,我们将有外部子矩阵(元素5到16)和内部子矩阵(元素1到4)。
现在,对于每个级别,您应该遍历四个边缘,并用所需的元素填充它们。你可以从里到外或从里到外。我会外出。我们保留一个最初为n*n
的计数器(在我们的示例中为16)。
i
从1
转到n/2
:
首先取下边缘(外层的元素16-13)。我们从x[n-i+1][i]
转到x[n-i+1][n-i+1]
并填写(第一级为16,15,14,13,第二级为4,3)
然后我们采取右边缘(外层的元素12-10)。我们从x[n-i][n-i+1]
转到x[i][n-i+1]
(元素12,11,10为外层)。
然后我们采取上边缘(外层的元素9-7)。我们从x[i][n-i]
转到x[i][i]
(外层的元素9,8,7)
最后我们采用左边缘(外层的元素6-5)。我们从x[i+1][i]
转到x[n-i][i]
并填充那一侧(外层为6,5)。
如果n
是奇数,最后你会得到中间元素。然后,您所要做的就是分配x[n/2+1][n/2+1] = 1
我希望我明白这个想法;如果你有什么不明白的地方,请问。
我也没有实施解决方案,因为我认为你遇到的问题只是想法,而不是实现
答案 1 :(得分:1)
在迭代矩阵时,您可以使用一个很好的想法来改变方向。请看下表。输入(dX,dY)是增量值中的前一个方向,输出(cwdx,cwdy)是下一个顺时针方向,输出(ccwdx,ccwdy)是下一个逆时针方向(坐标(0,0))在左上角):
dx dy | cwdx cwdy | ccwdx ccwdy
-------------------------------
1 0 | 0 1 | 0 -1
0 1 | -1 0 | 1 0
-1 0 | 0 -1 | 0 1
0 -1 | 1 0 | -1 0
因此,给定方向(dx,dy)顺时针转动你需要方向(-dy,dx),逆时针转动你需要方向(dx,-dy)。这意味着您不需要在代码中使用开关来转向,只需使用三行代码即可:
temp = dx; // this is for clockwise turn
dx = -dy;
dy = temp;
还有一个小技巧。要填充矩阵,您实际上可以从最后和最大数字开始,然后转到中心和数字1.如果从边缘开始并转到中心,那么您可以将数字填入一条直到可以(直到您到达矩阵的边缘或另一个数字)。如果由于(x + dx,y + dy)不能“填充”而无法填写当前方向,则改变方向。
答案 2 :(得分:1)
最简单的想法是从螺旋结束开始并继续前进。
有四个变量(left
,top
,right
,bottom
),可以告诉您从每一方面填充了多少。
制作适当大小的矩阵。
将left = top = 0
和right
以及bottom
初始化为最后一列和行索引。
填写bottom
的{{1}}行 - > left
。将right
减少一个。
从bottom
填写right
- > bottom
。将top
减少一个。
从right
填写top
- > right
。将left
增加一个。
从top
填写left
- > top
。将bottom
增加一个。
迭代直到你填满整个矩阵。
答案 3 :(得分:1)
如何应用右手规则(就像解决迷宫一样)。
走完后,考虑每个牢房。
答案 4 :(得分:1)
这是Java程序执行螺旋矩阵访问的片段。它跟踪方向的变化,以感知在任何给定方向上行进时可以进行多少次访问。简化此问题的模式是,在任何指定方向上旅行时,下次访问该方向时,访问次数将减少一次。更简单地说,如果你第一次沿水平方向旅行,那么下次你在水平方向旅行时你将进行6次访问,你将进行5次访问。还应注意,水平和垂直访问是分开跟踪的。在需要改变方向之后,使用下面的单个等式来计算给定方向的访问次数。该等式通过从方向变化的总数中导出并使用mod作为选择器来选择垂直或水平。最后,考虑作为沿着矩阵移动的蛇的访问我将步骤/列的变化表示为速度(dy和dx)。正如另一个人指出的那样,可以使用一种模式,并用dy和dx的公式表示。
int[][] matrix = { { 1, 2, 3, 4, 5, 6, 7, 8 },
{ 24, 25, 26, 27, 28, 29, 30, 9 },
{ 23, 40, 41, 42, 43, 44, 31, 10 },
{ 22, 39, 48, 47, 46, 45, 32, 11 },
{ 21, 38, 37, 36, 35, 34, 33, 12 },
{ 20, 19, 18, 17, 16, 15, 14, 13 } };
int n = matrix.length;
int m = matrix[0].length;
int row = 0;
int col = 0;
int dx = 1;
int dy = 0;
int dirChanges = 0;
int visits = m;
for (int i = 0; i < n * m; i++) {
System.out.print(matrix[row][col] + " ");
visits--;
if (visits == 0) {
visits = m * (dirChanges %2) + n * ((dirChanges + 1) %2) - (dirChanges/2 - 1);
int temp = dx;
dx = -dy;
dy = temp;
dirChanges++;
}
col += dx;
row += dy;
}
该程序的输出是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
答案 5 :(得分:0)
这是一个用PHP编写的递归解决方案。
<?php
header('Content-type: text/plain');
function fill($x, $y, $dir, $leftInDir, $index, $stepSize, $stop){
global $out;
// set the value for the current item //
$out[$y][$x] = $index;
// everything that comes after this point is computing for the parameters of the next call //
// activate this for debugging //
//echo $x, ',', $y, ',', $dir, ',', $leftInDir, ',', $index, ',', $stepSize, ',', $stop, "\n";
// decrease the number of steps left to take in the current direction //
$leftInDir--;
// check if this is the last item //
if($index == $stop)
return;
// we're going up for the next item //
if($dir == 'U')
$y--;
// we're going right for the next item //
if($dir == 'R')
$x++;
// we're going down for the next item //
if($dir == 'D')
$y++;
// we're going left for the next item //
if($dir == 'L')
$x--;
// if this was the last step in this direction we need to change the direction //
if($leftInDir == 0){
// after two direction changes we need to increase the numbers of steps to take //
if($dir == 'D' || $dir == 'U'){
$stepSize++;
}
// update the direction clockwise //
if($dir == 'U')
$dir = 'R';
else if($dir == 'R')
$dir = 'D';
else if($dir == 'D')
$dir = 'L';
else if($dir == 'L')
$dir = 'U';
// set the number of steps left as the step size //
$leftInDir = $stepSize;
}
// increase the number to put in the cell //
$index++;
// call for the next item //
fill($x,$y,$dir,$leftInDir,$index,$stepSize,$stop);
}
// set the size //
$size = 100;
// start the process from the center of the matrix //
fill((int)$size/2, (int)$size/2, 'R', 1, 1, 1, $size*$size);
// just output //
ksort($out);
foreach($out as $row){
ksort($row);
foreach($row as $item){
echo str_pad($item, 7);
}
echo "\n";
}
?>
这个原则非常直接(好吧,不是直的,而是螺旋式,向前:))。你从1
所在的地方开始,然后开始行走。 1右,1下,2左,2上,右3等,直至到达n*n
。
我把它写成递归函数,但它可以很容易地转换为循环。
答案 6 :(得分:0)
至#1
我编写了程序但结果如下:
00000
10000
11000
11100
.....
我不知道也许我没有理解你的algorythm或任何其他问题。 这是代码:
n:=16;
x:=1;
For i:=1 to (n div 2) do
begin
For p:=i to n-i+1 do
begin
a[n-i+1,p]:=x;
end;
For q:=n-i to i do
begin
a[q,n-i+1]:=x;
end;
For o:=n-i to i do
begin
a[i,o]:=x;
end;
For u:=i+1 to n-i do
begin
a[u,i]:=x;
end;
end;
所以我尝试将#2程序从php编写为pascal并且它可以工作。 现在我将修复它顺时针写入数字并从数组中心开始。
非常感谢大家。
答案 7 :(得分:0)
CurValue = n * n;
终点是最左下点。
我们将从终点访问第一点(我们通过访问分配值)
每个单元格在开头都没有值。
x = n-1;
y = 0;
arr[x][y] = CurValue;
while ( CurValue greater than zero )
{
keep going right until you face a cell that has non-zero value or until you reach the most right cell
keep going top until you face a cell that has non-zero value or until you reach the most top cell
keep going left until you face a cell that has non-zero value or until you reach the most left cell
keep going down until you face a cell that has non-zero value or until you reach the most down cell
}
note: with each cell you visit then do the following :
CurValue --;
Assign CurValue to the current visited cell;
我希望上面的算法清楚明白。
答案 8 :(得分:0)
你的意思是它必须从左到右,从上到下打印出数字?有助于知道要制作正方形数字,可以将连续的奇数加在一起 - 1 + 3 + 5 + 7 + 9 + 11 = 36。
在这个螺旋中,左边缘很简单......除了底行。因此,一种方法是编写算法,就好像螺旋是一个更大的循环,但不要打印出第一行以及第一列和最后一列。
答案 9 :(得分:0)
import java.util.Scanner;
class CircularMatrixFromInnerClockwise
{
Scanner sc= new Scanner(System.in);
void main()
{
System.out.println("Enter size.");
int n=sc.nextInt();
int a[][]= new int [n][n];
int r1,c1,r2,c2;
if(n%2==0)
{
r1=n/2-1;
c1=n/2-1;
r2=n/2-1;
c2=n/2-1;
}
else
{
r1=(n+1)/2-1;
c1=(n+1)/2-1;
r2=(n+1)/2-1;
c2=(n+1)/2-1;
}
int k=1;
do
{
if(c2<n-1&&r2<n-1)
{
r2++;
c2++;
}
for(int i=c1;i<=c2;i++)
a[r1][i]=k++;
if(k>=n*n)
break;
for(int i=r1+1;i<=r2;i++)
a[i][c2]=k++;
if(k>=n*n)
break;
if(c1>0&&r1>0)
{
c1--;
r1--;
}
for(int i=c2-1;i>=c1;i--)
a[r2][i]=k++;
if(k>=n*n)
break;
for(int i=r2-1;i>=r1+1;i--)
a[i][c1]=k++;
if(k>=n*n)
break;
}while(k<=n*n);
System.out.println("Circular matrix");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
System.out.print( a[i][j]+"\t");
}
System.out.println();
}
}
}
你是从左到右,然后是下来。左,上,又一遍。希望能帮助到你。 :)