//在N行N列的数阵中, 数K(1〈=K〈=N)在每行和每列中出现且仅
// 出现一次,这样的数阵叫N阶拉丁方阵。例如下图就是一个五阶拉丁方阵。
// 编一程序,从键盘输入N值后,打印出所有不同的N阶拉丁方阵,并统计个数。// 1 2 3 4 5
// 2 3 4 5 1
// 3 4 5 1 2
// 4 5 1 2 3
// 5 1 2 3 4
// 出现一次,这样的数阵叫N阶拉丁方阵。例如下图就是一个五阶拉丁方阵。
// 编一程序,从键盘输入N值后,打印出所有不同的N阶拉丁方阵,并统计个数。// 1 2 3 4 5
// 2 3 4 5 1
// 3 4 5 1 2
// 4 5 1 2 3
// 5 1 2 3 4
private int[] num = null; public LaDing(int n) {
num = new int[n];
for (int i = 0; i < num.length; i++) {
num[i] = i + 1;
}
} public int get(int row, int col) {
return num[(row + col) % num.length];
} public void print() {
for (int i = 0; i < num.length; i++) {
for (int j = 0; j < num.length; j++) {
System.out.print(get(i, j) + " ");
}
System.out.println();
}
}
}
private int n = 1; public LaDing(int n) {
this.n = n;
} public int get(int row, int col) {
return (row + col) % n + 1;
} public void print() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(get(i, j) + " ");
}
System.out.println();
}
}
}
import java.io.*;public class LatinSquareMatrix { //方阵阶数
int n;
//矩阵数组
int[][] arr ;
public LatinSquareMatrix(int n) {
// TODO Auto-generated constructor stub
this.n = n;
arr = new int[n][n];
makeMatrix(n);
}
public void makeMatrix(int n){
for (int i=0;i<n;i++){
arr[0][i] = i+1;
}
for (int j=1;j<n;j++){
for (int k=0;k<n;k++){
if (arr[j-1][k]==n){
arr[j][k]=1;
} else {
arr[j][k]=arr[j-1][k]+1;
}
}
}
}
public void printMatrix(){
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
System.out.print(arr[i][j]);
}
System.out.println();
}
System.out.println("共"+n*n+"个数字");
}
public static void main(String[] args) throws IOException {
System.out.print("请输入:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String num ="";
try
{
num = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
LatinSquareMatrix lsm = new LatinSquareMatrix(Integer.parseInt(num));
lsm.printMatrix();
}
}
运行结果:请输入:5
12345
23451
34512
45123
51234
共25个数字
private int n;
public LaDing(int n) {
this.n = n;
}
public int get(int row,int col) {
return (row+ col)% n+1;
}
public void print() {
for (int i=0; i< n; i++) {
for (int j=0; j< n; j++) {
System.out.print(get(i, j)+" ");
}
System.out.println();
}
}
public static void main(String[] args) throws IOException {
int n = 1;
String num = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while((num = br.readLine()) != null) {
n = Integer.parseInt(num);
break;
}
LaDing ld = new LaDing(n);
ld.print();
}
}还不怎么完善,自己改进改进!
我用的是回溯法,能够打印所有的方阵。
对于N=3时,有12个结果。N=4时,有576个结果。N=5时,结果太多了(>80000),打印要很久。
N=3时的结果如下:
1
123
231
312
================
2
123
312
231
================
3
132
213
321
================
4
132
321
213
================
5
213
132
321
================
6
213
321
132
================
7
231
123
312
================
8
231
312
123
================
9
312
123
231
================
10
312
231
123
================
11
321
132
213
================
12
321
213
132
================
class LaDing {
final int n;
int[][] m;
int count = 0;
LaDing(int n) {
this.n = n;
m = new int[n][n];
fill(0);
}
boolean check(int i, int j, int a) {
for(int col=0; col<j; col++)
if(m[i][col] == a) return false;
for(int row=0; row<i; row++)
if(m[row][j] == a) return false;
return true;
}
void fill(int i) {
int row = i/n;
int col = i%n;
for(int a=1; a<=n; a++) {
if(check(row, col, a)) {
m[row][col] = a;
if(i == n*n-1) {
count++;
System.out.println(count);
for(int[] line : m) {
for(int x : line)
System.out.print(x);
System.out.println();
}
System.out.println("================");
}
else fill(i+1);
}
}
}
public static void main(String[] args) {
new LaDing(3);
}
}
可以加个条件语句,决定是否打印:
if(print) { .... }如果不打印数组,只输出总数的话,还是很快的
N=5时 结果总数为 161280可以利用对称性,来加速计算,把一个结果上下翻转、左右翻转,镜像翻转,交换两列,交换两行...,等等操作都可以得到新的结果。但是比较麻烦,因为你得保证没有重复的。
然后生成N-1组(重点)标记,
利用对称性,来加速计算,把一个组里面的行列交换两行...可迅速计算出有N个排列
这样就可以得出总共有(N-1)*N!个结果
利用标记获取序列的元素打印
列举arraylist[3*2]=
123 0
132 1
213 2
231 3
312 4
321 5
生成3-1=2组基础拉丁方阵
123 132
231 213
312 312
标记034,125
利用交换,生成最后的标记,这里也可以用arraylist进行移位
输出结果:(N-1)*N!
打印结果;
列举arraylist[3*2]=
123 0
132 1
213 2
231 3
312 4
321 5
生成P(N-1)!=2组基础拉丁方阵
123 132
231 213
312 312
标记034,125
利用交换,生成最后的标记,这里也可以用arraylist进行移位
输出结果:P(N-1)!*N!
打印结果;找个才是
class LaDing {
private int n = 1; public LaDing(int n) {
this.n = n;
} public int get(int row, int col) {
return (row + col) % n + 1;
} public void print() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(get(i, j) + " ");
}
System.out.println();
}
}
public static void main(String args[]) {
new LaDing(5).print() ;
}
}
很强
另外,上面写错了点:
应该是 生成(N-1)!(N-2)!···2!*1组(重点)标记所以生成的总数是:*N(N-1)!(N-2)···2!*1
n=3, 为12
n=4 288
N!(N-1)!(N-2)···2!*1