5-9 拉丁矩阵问题
问题描述
现有 n 种不同形状的宝石,每种宝石有足够多颗。欲将这些宝石排列成 m 行 n 列的一个矩阵,m≤n,使矩阵中每一行和每一列的宝石都没有相同形状。试设计一个算法,计算 出对于给定的 m 和 n,有多少种不同的宝石排列方案。
对于给定的 m 和 n,计算出不同的宝石排列方案数。
数据输入:
第 1 行有 2 个正整数 m 和 n,0< m≤ n< 9。
Java
package Chapter5HuiSuFa;
import java.util.Scanner;
public class LaDingJuZhen {
private static int m,n;
private static int[][] board;
private static double count;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while (true){
count = 0.0;
m = input.nextInt();
n = input.nextInt();
board = new int[n+1][n+1];
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
board[i][j] = j;
for(int i=2; i<=n; i++)
swap(board[i],1,i);
if(m == n) m--;
backtrack(2,2);
output(count);
}
}
private static void output(double count){
double result = factorial(n)*factorial(n-1)*count/factorial(n-m);
System.out.println(result);
}
private static long factorial(int n){
if(n==1 || n==0) return 1;
else return n*factorial(n-1);
}
private static void backtrack(int r, int c){
for(int i=c; i<=n; i++)
if(ok(r,c,board[r][i])){
swap(board[r],c,i);
if(c == n){
if(r == m) count += 1.0;
else backtrack(r+1,2);
}else backtrack(r,c+1);
swap(board[r],c,i);
}
}
private static boolean ok(int r, int c, int k){
for(int i=1; i<r; i++)
if(board[i][c] == k)
return false;
return true;
}
private static void swap(int[] board, int c, int i){
int tmp = board[c];
board[c] = board[i];
board[i] = tmp;
}
}
Input & Output
3 3
12.0
Reference
王晓东《计算机算法设计与分析》(第3版)P182