算法设计与分析: 5-9 拉丁矩阵问题

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

猜你喜欢

转载自blog.csdn.net/ioio_/article/details/81105477
5-9