您的位置:首页 > 其它

[算法设计与分析]3.2.5构造趣味矩阵(规律阵+螺旋阵+魔方阵)

2018-03-28 17:31 423 查看
#include<stdio.h>
#include<iostream>

using namespace std;

const int N = 5;
void RegularMatrix();
void ScrewMatrix1();
void ScrewMatrix2();
void MagicMatrix();

int main ()
{
RegularMatrix();
ScrewMatrix1();
ScrewMatrix2();
MagicMatrix();
}

void RegularMatrix()
{
int i, j;
int a[N + 1][N + 1];
for(i = 1; i <= N; i++)
{
for(j = 1; j <= N; j++)//根据两条对角线与行列下标的关系 进行划分
{
if(i == j || i + j == N + 1)
a[i][j] = 0;
if(i + j < N + 1 && i < j)
a[i][j] = 1;
if(i + j < N + 1 && i > j)
a[i][j] = 2;
if(i + j > N + 1 && i < j)
a[i][j] = 3;
if(i + j > N + 1 && i > j)
a[i][j] = 4;
}
}
for(i = 1; i <= N; i++)
{
for(j = 1; j <= N; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
}

void ScrewMatrix1()
{
int N = 4;
int a[N + 1][N + 1];
int num = 1;
int circle, left, lower, right, upper;

for(circle = 1; circle <= N / 2; circle++)//circle代表的是第几圈
{
for(left = circle; left <= N - circle; left++)//left代表的是左侧 left的初始值一定是一个变化的数
//否则无法做到在circle循环赋值 同时left的最大值一定与n和circle相关
{
a[left][circle] = num++;
}
for(lower = circle; lower <= N - circle; lower++)//lower的初始值一定与circle相关 是一个变化的值
//lower的最大值与circle相关 也等于此时的left(循环结束条件是left+1之后的结果)
{
a[N + 1 - circle][lower] = num++;//下边的行号与left的最大值相同 列号不断变化
}
for(right = lower; right >= circle + 1; right--)//right的最小值与circle相关
{
a[right][N + 1 - circle] = num++;
}
for(upper = N + 1 - circle; upper >= circle + 1; upper--)//行号不变
{
a[circle][upper] = num++;
}
}
if(N % 2)
{
a[(N + 1) / 2][(N + 1) / 2] = N * N;
}

for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++)
printf("%3d", a[i][j]);
cout <<endl;
}
cout << endl;
}

//通过引入数组b,变量t和k将一圈中的上下左右4种变化情况构造成一个循环不变式
void ScrewMatrix2()
{
int N = 4;
int a[N + 1][N + 1], b[2] = {0, 1};//b[0]表示存储矩阵的数组a的行下标,b[1]表示列下标
int i, j, k, y;
k = N;
int t = 1;
int num = 1;

while(num <= N * N)
{//规模为N的矩阵的一圈共有4N-4个元素 而本算法的半圈是不对称的(为了构成循环,因为循环的每一圈矩阵规模都不同)
for(y = 1; y <= 2 * k - 1; y++)//y用作循环变量模拟半圈数据处理的过程
{//在每个半圈中 当y=1->k的时候 y/(k+1)的值始终为0 这样列下标b[1]不会发生变化 而行下标b[0]则不断地+t变化(根据t的正负不同)
//当y=k+1->2k-1时 行下标b[0]不会发生变化b[1]随t变化
b[y / (k + 1)] = b[y / (k + 1)] + t;//t=1时处理左下角 t=-1时处理右下角
a[b[0]][b[1]] = num++;
}
k--;
t = -t;
}
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++)
printf("%3d", a[i][j]);
cout <<endl;
}
cout << endl;
}

void MagicMatrix()
{
int N = 3, m;
int a[N + 1][N + 1] = {0};

int i = 1, j = (N + 1) / 2;//i,j分别代表行列坐标
int prei, prej;

for(m = 1; m <= N * N; m++)//m表示要填入的数
{
a[i][j] = m;
prei = i;//因为涉及到对当前元素的前一个元素的操作 因此需要记录之前元素的行列下标
prej = j;
i = i - 1;//按照魔方阵的规则
j = j - 1;
if(i == 0)//行下标或者列下标出界
i = N;
if(j == 0)
j = N;
if(a[i][j])//该位置已经有数
{
i = prei + 1;
j = prej;
}

}
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++)
printf("%3d", a[i][j]);
cout <<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息