描述
幻方根据阶数不同可分为奇阶幻方、单偶幻方和双偶阶幻方。对于奇阶幻方的构造,可以通过Loubere法,即不断地向右上角填数。遇到有数的格折回来再填。对于双偶阶幻方,可以用Spring法构造:以行为主序列将1-n^2依次填入到方格,然后再将幻方平分四块,左上角的那一块i+j等于偶数的方格的数字与它的中心对称方格的交换,右上角的那一块i+j等奇数的方格的数字与它中心对称方格进行交换。单偶阶幻方可以划分成
AC
DB
四块,每块为一个奇阶幻方,然后将构造四个幻方,再将A幻方的m列与D的对应列进行交换,B的m-1列与C的对应列进行交换。(这个算法好像有问题,计算6阶幻方时没有问题,但计算10阶时有问题)。
实现
用一个Magic类封装,只需要给定一个幻方的阶数,它会自动判断阶数然后调用相应的构造方法。
奇阶幻方的构造调用:filloddmagic
单偶阶幻方的构造调用:fill2timesmagic
双偶阶幻方的构造调用:fill4timesmagic
1
#include <iostream>
2
#include <iomanip>
3
#include <stdlib.h>
4
5
using namespace std;
6
7
/**
8
* 幻方类,可以计算奇阶幻方,双偶阶幻方,单偶阶幻方
9
* 目前单偶阶幻方还有点问题。
10
* 构造方法:
11
* 奇阶幻方: Loubere法
12
* 双偶阶幻方:Spring法
13
* 单偶阶幻方:Strachey法
14
*
15
* zyl 2008.1.21
16
*/
17
typedef int MT;
18
19
class Magic
20
{
21
private:
22
MT **matrix;
23
int size;
24
25
void zeromatrix();
26
void deletematrix();
27
void filloddmagic();
28
void fill2timesmagic();
29
void fill4timesmagic();
30
void movenext(int &i, int &j);
31
inline void swap(MT &v1, MT &v2);
32
public:
33
Magic();
34
Magic(int size);
35
virtual ~Magic();
36
inline void setsize(int size);
37
inline int getsize()const;
38
void dofill();
39
void printmagic();
40
};
41
42
void Magic::setsize(int size)
43
{
44
if(size <= 2)
45
return;
46
this->size = size;
47
}
48
49
int Magic::getsize()const
50
{
51
return size;
52
}
53
54
void Magic::swap(MT &v1, MT &v2)
55
{
56
MT temp = v1;
57
v1 = v2;
58
v2 = temp;
59
}
60
61
void Magic::zeromatrix()
62
{
63
if(matrix == NULL)
64
return;
65
66
for(int i=0;i<size;i++)
67
{
68
// memset(matrix, 0, size * sizeof(MT));
69
for(int j=0;j<size;j++)
70
matrix[i][j] = 0;
71
}
72
}
73
74
void Magic::deletematrix()
75
{
76
if(matrix == NULL)
77
return;
78
for(int i=0;i<size;i++)
79
delete []matrix[i];
80
delete []matrix;
81
matrix = NULL;
82
}
83
84
void Magic::movenext(int &i, int &j)
85
{
86
if(i == 0 && j == size - 1)
87
{
88
i++;
89
return;
90
}
91
//i = (--i)%size;
92
i = (i + size - 1)%size;
93
j = (j + 1)%size;
94
95
if(matrix[i][j] > 0)
96
{
97
i = (i+2)%size;
98
//j = (j--)%size;
99
j = (j + size - 1)%size;
100
}
101
}
102
103
Magic::Magic()
104
{
105
size = 0;
106
matrix = NULL;
107
}
108
109
Magic::Magic(int size)
110
{
111
this->size = size;
112
matrix = NULL;
113
}
114
115
Magic::~Magic()
116
{
117
deletematrix();
118
}
119
120
void Magic::dofill()
121
{
122
if(size == 0)
123
return;
124
deletematrix();
125
126
matrix = new MT*[size];
127
for(int i=0;i<size;i++)
128
matrix[i] = new MT[size];
129
130
switch(size%4)
131
{
132
case 1:
133
case 3: filloddmagic(); break;
134
case 0: fill4timesmagic(); break;
135
case 2: fill2timesmagic(); break;
136
}
137
}
138
139
void Magic::filloddmagic()
140
{
141
this->zeromatrix();
142
int i, j;
143
144
// 初始位置
145
i = 0;
146
j = (size - 1)/2;
147
148
for(MT v=1; v <= size * size; v++)
149
{
150
// fill
151
matrix[i][j] = v;
152
// get next pos
153
movenext(i, j);
154
}
155
}
156
157
void Magic::fill2timesmagic()
158
{
159
int half = size/2;
160
Magic hm(half);
161
hm.dofill();
162
163
int i, j;
164
int step[4];
165
step[0] = 0;
166
step[1] = half * half;
167
step[2] = step[1] + step[1];
168
step[3] = step[2] + step[1];
169
170
// fill
171
for(i=0; i<half;i++)
172
for(j=0;j<half;j++)
173
{
174
matrix[i][j] = hm.matrix[i][j] + step[0]; // A
175
matrix[i][j + half] = hm.matrix[i][j] + step[2]; // C
176
matrix[i + half][j + half] = hm.matrix[i][j] + step[1]; // B
177
matrix[i + half][j] = hm.matrix[i][j] + step[3]; // D
178
}
179
180
// exchange
181
int m = (size - 2)>>2; // 右移,相当于除以4
182
int mm = size - (m - 1);
183
for(i=0;i<half;i++)
184
for(j=0;j<m;j++)
185
{
186
swap(matrix[i][j], matrix[i + half][j]);
187
if(j > 0)
188
swap(matrix[i][j + mm], matrix[i + half][j + mm]);
189
}
190
}
191
192
void Magic::fill4timesmagic()
193
{
194
int v = 0;
195
int i, j;
196
for(i=0;i<size;i++)
197
for(j=0;j<size;j++)
198
matrix[i][j] = ++v;
199
// exchange
200
i=0, j=0;
201
int before = size/2 - 1;
202
203
for(i=0;i<=before;i++)
204
{
205
// 左半部分
206
j = (i%2==0? 0:1);
207
for(;j<=before;j+=2)
208
swap(matrix[i][j], matrix[size-i-1][size-j-1]);
209
// 右半部分的
210
j--;
211
if(j<=before)
212
j += 2;
213
for(; j<=size-1; j+=2)
214
swap(matrix[i][j], matrix[size-i-1][size-j-1]);
215
}
216
}
217
218
void Magic::printmagic()
219
{
220
if(matrix == NULL)
221
return;
222
223
int w = 1;
224
if(size>= 4 && size <= 9)
225
w = 2;
226
else if(size>= 10 && size <= 31)
227
w = 3;
228
else if(size>= 32 && size <= 99)
229
w = 4;
230
231
for(int i=0;i<size;i++)
232
{
233
for(int j=0;j<size;j++)
234
cout<<setw(w)<<matrix[i][j]<<' ';
235
cout<<endl;
236
}
237
238
cout<<endl;
239
int total = 0;
240
for(int j=0;j<size;j++)
241
total += matrix[0][j];
242
cout<<"第0行和:"<<total<<endl;
243
244
total = 0;
245
for(int j=0;j<size;j++)
246
total += matrix[j][0];
247
cout<<"第0列和:"<<total<<endl;
248
}
249
250
251
int main(int argc, char *argv[])
252
{
253
int size;
254
cout<<"输入幻方的阶数(>=3):";
255
cin>>size;
256
cout<<endl;
257
258
if(size <= 2)
259
return 0;
260
Magic m;
261
m.setsize(size);
262
m.dofill();
263
m.printmagic();
264
265
266
system("PAUSE");
267
return 0;
268
}
269
270
#include <iostream>2
#include <iomanip>3
#include <stdlib.h>4

5
using namespace std;6

7
/**8
* 幻方类,可以计算奇阶幻方,双偶阶幻方,单偶阶幻方9
* 目前单偶阶幻方还有点问题。10
* 构造方法:11
* 奇阶幻方: Loubere法12
* 双偶阶幻方:Spring法 13
* 单偶阶幻方:Strachey法14
* 15
* zyl 2008.1.2116
*/17
typedef int MT;18

19
class Magic20
{21
private:22
MT **matrix;23
int size;24
25
void zeromatrix();26
void deletematrix();27
void filloddmagic();28
void fill2timesmagic();29
void fill4timesmagic();30
void movenext(int &i, int &j);31
inline void swap(MT &v1, MT &v2);32
public:33
Magic();34
Magic(int size);35
virtual ~Magic();36
inline void setsize(int size);37
inline int getsize()const;38
void dofill();39
void printmagic();40
};41

42
void Magic::setsize(int size)43
{44
if(size <= 2)45
return;46
this->size = size;47
}48

49
int Magic::getsize()const50
{51
return size;52
}53

54
void Magic::swap(MT &v1, MT &v2)55
{56
MT temp = v1;57
v1 = v2;58
v2 = temp;59
}60

61
void Magic::zeromatrix()62
{63
if(matrix == NULL)64
return;65

66
for(int i=0;i<size;i++)67
{68
// memset(matrix, 0, size * sizeof(MT));69
for(int j=0;j<size;j++)70
matrix[i][j] = 0;71
}72
}73

74
void Magic::deletematrix()75
{76
if(matrix == NULL)77
return;78
for(int i=0;i<size;i++)79
delete []matrix[i];80
delete []matrix;81
matrix = NULL;82
}83

84
void Magic::movenext(int &i, int &j)85
{86
if(i == 0 && j == size - 1)87
{88
i++;89
return;90
}91
//i = (--i)%size;92
i = (i + size - 1)%size;93
j = (j + 1)%size;94
95
if(matrix[i][j] > 0)96
{97
i = (i+2)%size;98
//j = (j--)%size;99
j = (j + size - 1)%size;100
}101
}102

103
Magic::Magic()104
{105
size = 0;106
matrix = NULL;107
}108

109
Magic::Magic(int size)110
{111
this->size = size;112
matrix = NULL;113
}114

115
Magic::~Magic()116
{117
deletematrix();118
}119

120
void Magic::dofill()121
{122
if(size == 0)123
return;124
deletematrix();125
126
matrix = new MT*[size];127
for(int i=0;i<size;i++)128
matrix[i] = new MT[size];129
130
switch(size%4)131
{132
case 1:133
case 3: filloddmagic(); break;134
case 0: fill4timesmagic(); break;135
case 2: fill2timesmagic(); break;136
}137
}138

139
void Magic::filloddmagic()140
{141
this->zeromatrix();142
int i, j;143
144
// 初始位置 145
i = 0;146
j = (size - 1)/2;147
148
for(MT v=1; v <= size * size; v++)149
{150
// fill151
matrix[i][j] = v;152
// get next pos153
movenext(i, j);154
}155
}156

157
void Magic::fill2timesmagic()158
{159
int half = size/2;160
Magic hm(half);161
hm.dofill();162
163
int i, j;164
int step[4];165
step[0] = 0;166
step[1] = half * half;167
step[2] = step[1] + step[1];168
step[3] = step[2] + step[1];169
170
// fill171
for(i=0; i<half;i++)172
for(j=0;j<half;j++)173
{174
matrix[i][j] = hm.matrix[i][j] + step[0]; // A175
matrix[i][j + half] = hm.matrix[i][j] + step[2]; // C176
matrix[i + half][j + half] = hm.matrix[i][j] + step[1]; // B177
matrix[i + half][j] = hm.matrix[i][j] + step[3]; // D178
}179
180
// exchange181
int m = (size - 2)>>2; // 右移,相当于除以4182
int mm = size - (m - 1);183
for(i=0;i<half;i++)184
for(j=0;j<m;j++)185
{186
swap(matrix[i][j], matrix[i + half][j]);187
if(j > 0)188
swap(matrix[i][j + mm], matrix[i + half][j + mm]);189
} 190
}191

192
void Magic::fill4timesmagic()193
{194
int v = 0;195
int i, j;196
for(i=0;i<size;i++)197
for(j=0;j<size;j++)198
matrix[i][j] = ++v;199
// exchange200
i=0, j=0;201
int before = size/2 - 1;202
203
for(i=0;i<=before;i++)204
{205
// 左半部分 206
j = (i%2==0? 0:1);207
for(;j<=before;j+=2)208
swap(matrix[i][j], matrix[size-i-1][size-j-1]);209
// 右半部分的 210
j--;211
if(j<=before)212
j += 2;213
for(; j<=size-1; j+=2)214
swap(matrix[i][j], matrix[size-i-1][size-j-1]);215
}216
}217

218
void Magic::printmagic()219
{220
if(matrix == NULL)221
return;222
223
int w = 1;224
if(size>= 4 && size <= 9)225
w = 2;226
else if(size>= 10 && size <= 31)227
w = 3;228
else if(size>= 32 && size <= 99)229
w = 4;230
231
for(int i=0;i<size;i++)232
{233
for(int j=0;j<size;j++)234
cout<<setw(w)<<matrix[i][j]<<' ';235
cout<<endl;236
}237
238
cout<<endl;239
int total = 0;240
for(int j=0;j<size;j++)241
total += matrix[0][j];242
cout<<"第0行和:"<<total<<endl;243
244
total = 0;245
for(int j=0;j<size;j++)246
total += matrix[j][0];247
cout<<"第0列和:"<<total<<endl;248
}249

250

251
int main(int argc, char *argv[])252
{253
int size;254
cout<<"输入幻方的阶数(>=3):";255
cin>>size;256
cout<<endl;257
258
if(size <= 2)259
return 0;260
Magic m;261
m.setsize(size);262
m.dofill();263
m.printmagic();264

265
266
system("PAUSE"); 267
return 0;268
}269

270




浙公网安备 33010602011771号