拉丁矩阵问题

 ">**问题描述
*现有n 种不同形状的宝石,每种宝石有足够多颗。
*将这些宝石排列成m行n 列的一个矩阵,m≤n,使矩阵中每一行和每一列的宝石都没有相同形状。
*设计一个算法,计算出对于给定的m和n,有多少种不同的宝石排列方案。
**编程任务
*对于给定的m和n,计算出不同的宝石排列方案数。
**数据输入 input.txt
*第一行有两个正整数m和n,0<m<=9
**数据输出 output.txt
*将计算出的宝石排列方案数输出到文件
**解决思路
*回溯,主要是行和列一起回溯
*二维数组board[m][n]存储宝石矩阵。每行初始化为单位排列,第一行从上到下为1,2,...m
**参考
*<a href="http://longgongshiye.blog.163.com/blog/static/17148259720117178143225/" target="_blank"> 参考代码 </a>
*/
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;
int const MAX = 9;
typedef int ARRAY2D[MAX][MAX];
ARRAY2D board;

int N(0), M(0),Count(0);


inline void readfile(const string &filename)
{
   FILE *stream;
   std::ios::sync_with_stdio(false);//加速
   freopen_s(&stream,filename.c_str(), "r", stdin);
   //scanf("%d",&a),cin可以跳过不合法字符
   cin >> M >> N;
   fclose(stdin);
}

template <typename T>
inline int writefile(string filename, T n)
{
   //freopen(filename.c_str(), "r", stdout);
   //fclose(stdout);
   ofstream ofile(filename.c_str(), ios_base::binary | ios_base::out);
   if (!ofile)
   {
       cerr << "cannot open file!\n";
       exit(1);
   }
   ofile << n;
   cout << "write over." << endl;
   return 0;
}



int bound(int r, int c)
{
   for (int i = 1; i < r; ++i)
       if (board[i][c] == board[r][c]) return 0;
   return 1;
}


void backtrack(int r, int c)
{
   if (r > M){
       ++Count;
       for (int i = 1; i <= M; ++i){
           for (int j = 1; j <= N; ++j)
               printf("%d", board[i][j]);
           printf("\n");
       }
       printf("\n");
       return;    
   }
   if (c > N){
       backtrack(r + 1, 1);
   }

   for (int i = c; i <= N; ++i){
       swap(board[r][c], board[r][i]);      //要先交换
       if (bound(r, c)) backtrack(r, c + 1);
       swap(board[r][c], board[r][i]);
   }
}

int main()
{
   string input = "input.txt";
   string output = "output.txt";

   readfile(input);             //get M and N
   for (int i = 1; i <= N; ++i){
       for (int j = 1; j <= N; ++j){
           board[i][j] = j;
       }
   }
   for (int i = 1; i <= N; ++i)
       swap(board[i][1], board[i][i]);

   backtrack(1, 1);
   writefile(output, Count);

   system("pause");
   return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值