#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
const int MAX = 50;
int n, m, k;
int times[MAX]; //每种宝石的重复次数
int id[MAX]; //每个宝石的价值序号
int board[MAX][MAX]; //宝石矩阵
//考察当前列宝石数是否多于应出现的次数
bool ok(int r, int c, int s)
{
int k = board[r][s];
int i;
if(s > c)
for(i=c; i<s; i++)
if(board[r][i] == k) //如果已经试过相同类型的宝石,这次就不再试了
return false;
int count = 0;
for(i=1; i<r; i++) //考察当前列宝石数是否多于应出现的次数
if(board[i][c] == k)
count++;
if(count >= times[k]) //times[k]表示种类为k的宝石应出现的次数
return false;
else
return true;
}
double num = 0; //不同的宝石排列方案数
//从上到下,从左到右递归搜索,即先行后列
void backtrack(int r, int c)
{
for(int i=c; i<=n; i++) //列
if(ok(r, c, i))
{
swap(board[r][c], board[r][i]);
if(c == n) //如果列考察完毕
{
if(r == m) //如果行考察完毕
{
num += 1.0;
//cout << num << " ";
return;
}
else
backtrack(r+1, 2); //考察下一行
}
else
backtrack(r, c+1); //考察下一列
swap(board[r][c], board[r][i]);
}
}
int main()
{
ifstream fin("重复拉丁.txt");
cout << "\n输入行数m:";
fin >> m; cout << m;
cout << "\n输入列数n:";
fin >> n; cout << n;
cout << "\n输入宝石价值种数:";
fin >> k; cout << k << endl;
int i, temp;
int t = 1;
for(i=1; i<=k; i++)
{
cout << "输入第" << i << "种宝石在每行每列出现的最多次数:";
fin >> times[i];
cout << times[i] << "\n";
temp = times[i];
while(temp>0)
{
id[t++] = i;
temp--;
}
}
int j;
for(i=1; i<=m; i++) //初始化为单位矩阵
for(j=1; j<=n; j++)
board[i][j] = id[j];
backtrack(2, 2);
cout << "\n不同的宝石排列方案数为:" << num;
cout << endl << endl;
return 0;
}
书上的正确答案为 84309,不知错在哪里