拉丁矩阵 回溯 c java

现有n种不同形状的宝石,每种宝石有足够多颗。欲将这些宝石排列成m行n列的一个矩阵,m n,使矩阵中每一行和每一列的宝石都没有相同形状。试设计一个算法,计算出对于给定的m和n有多少种不同的宝石排列方案。
方法一:(从左往右,从上往下,依次填写,保证上方,左方没有重复的)
import java.util.Scanner;

public class LaDingJuZhen3 {
	static int[][] x;
	static int m;    //行
	static int n;    //列
	static int mn;
	static int count=0;
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		m=input.nextInt();
		n=input.nextInt();
		mn=(m)*(n);
		input.close();
		x=new int[m][n];
		Backtrack(0);
		System.out.println(count);
	}
	public static void Backtrack(int t){
		int i=t/n;
		int j=t%n;
		if(t>=mn){
			count ++;
			return;
		}
		for (int k = 0; k < n ; k++) {
			if(isOk(i, j, k)){
				x[i][j]=k;
				Backtrack(t+1);
			}
		}
	}
	public static boolean isOk(int i,int j,int k){
		for (int l = 0; l < i; l++) {
			if(x[l][j]==k){
				return false;
			}
		}
		for (int l = 0; l < j; l++) {
			if(x[i][l]==k){
				return false;
			}
		}
		return true;
	}
}

方法2:每一行n个不同的数,行作为深度,求每一行的全排列,保证行列不重复


import java.util.Scanner;

public class LaDingJuZhen2 {
	static int[][] x;
	static int m;
	static int n;
	static int count=0;
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		m=input.nextInt();
		n=input.nextInt();
		input.close();
		x=new int[m+1][n+1];
		for (int i = 0; i < m+1; i++) {
			for (int j = 0; j < n+1; j++) {
				x[i][j]=j;
			}
		}
		Backtrack(1, 1);
		System.out.println(count);
	}
	public static void outPut(){
		for (int i = 1; i <= m; i++) {
			for (int j = 1; j <= n; j++) {
				System.out.print(x[i][j]+"  ");
			}
			System.out.println();
		}
		System.out.println();
	}
	public static boolean ok(int s,int t){
		for (int i = 1; i < s; i++) {
			for (int j = 1; j <= n; j++) {
				if(x[i][j]==x[s][j]) {
					return false;
				}
			}
		}
		return true;
	}
	public static void  swap(int x1,int y1,int x2,int y2){
		int t;
		t=x[x1][y1];
		x[x1][y1]=x[x2][y2];
		x[x2][y2]=t;
	}
	public static void Backtrack(int s,int t){   //s表示行  t表示列
		if(s>m){
			count++;
			outPut();
			return;
		}
		if(t>n){
			if(ok(s, t)){
				Backtrack(s+1, 1);
			}
		}
		for (int i = t; i <= n; i++) {
			swap(s, i, s, t);
			Backtrack(s, t+1);
			swap(s, i, s, t);
		}
	}
}

#include"iostream"
using namespace std;
int **x;
int count=0;
int s;
int t;
int m;
int n;
int no=0;
void OutPut()
{
 for(int i=1;i<=m;i++)
 {
  for(int j=1;j<=n;j++)
   cout<<x[i][j]<<ends;
  cout<<endl;
 }
// cout<<endl;
}
void swap(int &a,int &b)//要用引用
{
 int p;
 p=a;
 a=b;
 b=p;
}
int OK(int**x,int s,int t)
{
 for(int k=1;k<s;k++)
  for(int j=1;j<=n;j++)
         if(x[k][j]==x[s][j]) return 0;
 return 1;
}
void Backtrack(int s,int t)
{
 int j;
 if(s>m)
 {
  count++;
 // no++;
 // cout<<"矩阵:"<<no<<endl;
 // OutPut();
  return;
 }
 
 if(t>n)
 {  
  if(OK(x,s,t))
   Backtrack(s+1,1);
 }
 for(j=t;j<=n;j++)
 {
  swap(x[s][j],x[s][t]);
  Backtrack(s,t+1);
  swap(x[s][j],x[s][t]);
 }
}
void main()
{
 int i,j;
 cin>>n>>m;
 x=new int*[m+1];
 for(i=0;i<=m;i++)
     x[i]=new int[n+1];
 for(i=0;i<=m;i++)
  for(j=0;j<=n;j++)
   x[i][j]=j;
 Backtrack(1,1);
 cout<<count<<endl;
}
    原文作者:拉丁方阵问题
    原文地址: https://blog.csdn.net/foolsong/article/details/16985927
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞