前几天学校的mstc招新,没事凑个热闹,跑过去拿了一份笔试题目。
题目其实就是一个数独(sudoku)游戏的简化版本,关于数独大家可以去看看
这篇介绍 http://sudoku.chuchuang.net/
大体意思就是给定一个9*9的矩阵,初始时候里面有了一些1~9数字,
现在要求往矩阵中填入1~9的数字, 使得每行每列的数字不重复
9 0 5 8 0 4 0 2 0
8 0 0 1 0 5 0 0 9
1 0 0 0 0 0 5 0 3
0 0 0 3 9 0 8 0 0
2 0 8 0 0 0 7 0 1
3 0 9 0 8 1 0 0 0
5 0 4 0 0 0 0 1 0
7 0 0 6 0 0 0 0 0
0 8 0 5 0 3 9 0 0
初始矩阵如上.
好了, 附上我的以行为单位的回溯解法
这个和crj学长的解稍有不同,是两层回溯,可以求出全部的解,呵呵。
题目其实就是一个数独(sudoku)游戏的简化版本,关于数独大家可以去看看
这篇介绍 http://sudoku.chuchuang.net/
大体意思就是给定一个9*9的矩阵,初始时候里面有了一些1~9数字,
现在要求往矩阵中填入1~9的数字, 使得每行每列的数字不重复
9 0 5 8 0 4 0 2 0
8 0 0 1 0 5 0 0 9
1 0 0 0 0 0 5 0 3
0 0 0 3 9 0 8 0 0
2 0 8 0 0 0 7 0 1
3 0 9 0 8 1 0 0 0
5 0 4 0 0 0 0 1 0
7 0 0 6 0 0 0 0 0
0 8 0 5 0 3 9 0 0
初始矩阵如上.
好了, 附上我的以行为单位的回溯解法
这个和crj学长的解稍有不同,是两层回溯,可以求出全部的解,呵呵。
//
Solver For Number Puzzle From Microsoft Club
// 71105129 CloudiDust
#include < fstream >
#include < algorithm >
using namespace std;
struct FreqList
{
int num;
int count;
bool operator<(const FreqList& another) const
{
return (count > another.count);
}
} ;
const int boardSize = 9 ;
int gameBoard[boardSize][boardSize] = {{0,0}} ;
int columnInRow[boardSize + 1 ][boardSize];
bool isInColumn[boardSize + 1 ][boardSize];
bool isFixed[boardSize + 1 ][boardSize];
FreqList processList[boardSize];
void occupy( const int row, const int col, const int num)
{
gameBoard[row][col] = num;
columnInRow[num][row] = col;
isInColumn[num][col] = true;
}
void free( const int row, const int col)
{
int &num = gameBoard[row][col];
columnInRow[num][row] = -1;
isInColumn[num][col] = false;
num = 0;
}
void initialize()
{
// 初始化数字位置标记矩阵
for (int num = 0; num <= boardSize; ++num)
{
for (int index = 0; index < boardSize; ++index)
{
columnInRow[num][index] = -1;
isInColumn[num][index] = false;
isFixed[num][index] = false;
}
}
// 初始化处理顺序表
for (int num = 1; num <= boardSize; ++num)
{
processList[num - 1].num = num;
processList[num - 1].count = 0;
}
// 读入初始数据
ifstream dataFile("mcnp.in");
for (int rowIndex = 0; rowIndex < boardSize; ++rowIndex)
{
for (int columnIndex = 0; columnIndex < boardSize; ++columnIndex)
{
int temp;
dataFile >> temp;
if (temp)
{
occupy(rowIndex, columnIndex, temp);
isFixed[temp][rowIndex] = true;
++processList[temp - 1].count;
}
}
}
dataFile.close();
// 对处理顺序表进行排序
// 在初始数据中出现次数越多的数字,将越优先处理
sort(processList, processList + boardSize);
}
void print(ostream & resFile);
bool place( const int , const bool );
void process()
{
ofstream resFile("mcnp.out");
bool isPlaced[boardSize] = {false};
int stackTop = 0;
while (stackTop > -1)
{
if (stackTop == boardSize)
{
print(resFile);
--stackTop;
}
else
{
isPlaced[stackTop] = place(processList[stackTop].num,isPlaced[stackTop]);
if (isPlaced[stackTop])
++stackTop;
else
--stackTop;
}
}
resFile.close();
}
bool place( const int num, const bool hasBeenPlacedBefore)
{
int currentRow;
if (!hasBeenPlacedBefore)
{
currentRow = 0;
while ((currentRow < boardSize) && isFixed[num][currentRow]) ++currentRow;
}
else
{
currentRow = boardSize - 1;
while ((currentRow >= 0) && isFixed[num][currentRow]) --currentRow;
}
while (currentRow > -1)
{
if (currentRow == boardSize) return true;
else
{
int& prevColumn = columnInRow[num][currentRow];
int currentColumn = prevColumn + 1;
while (currentColumn < boardSize
&& (isInColumn[num][currentColumn]
|| gameBoard[currentRow][currentColumn] != 0))
++currentColumn;
// 找不到下一个合适的列吗?
if (currentColumn == boardSize)
{
//找不到,释放本行数据,回溯到上一可以修改的行
if (prevColumn > -1)
free(currentRow, prevColumn);
--currentRow;
while ((currentRow >= 0) && isFixed[num][currentRow]) --currentRow;
}
else
{
//找到了,填充新位置,选择下一可以修改的行
if (prevColumn > -1)
free(currentRow, prevColumn);
occupy(currentRow, currentColumn, num);
++currentRow;
while ((currentRow < boardSize) && isFixed[num][currentRow]) ++currentRow;
}
}
}
return false;
}
void print(ostream & resFile)
{
for (int rowIndex = 0; rowIndex < boardSize; ++rowIndex)
{
for (int columnIndex = 0; columnIndex < boardSize; ++columnIndex)
{
resFile << gameBoard[rowIndex][columnIndex] << " ";
}
resFile << endl;
}
resFile << endl;
}
int main()
{
initialize();
process();
return 0;
}
// 71105129 CloudiDust
#include < fstream >
#include < algorithm >
using namespace std;
struct FreqList
{
int num;
int count;
bool operator<(const FreqList& another) const
{
return (count > another.count);
}
} ;
const int boardSize = 9 ;
int gameBoard[boardSize][boardSize] = {{0,0}} ;
int columnInRow[boardSize + 1 ][boardSize];
bool isInColumn[boardSize + 1 ][boardSize];
bool isFixed[boardSize + 1 ][boardSize];
FreqList processList[boardSize];
void occupy( const int row, const int col, const int num)
{
gameBoard[row][col] = num;
columnInRow[num][row] = col;
isInColumn[num][col] = true;
}
void free( const int row, const int col)
{
int &num = gameBoard[row][col];
columnInRow[num][row] = -1;
isInColumn[num][col] = false;
num = 0;
}
void initialize()
{
// 初始化数字位置标记矩阵
for (int num = 0; num <= boardSize; ++num)
{
for (int index = 0; index < boardSize; ++index)
{
columnInRow[num][index] = -1;
isInColumn[num][index] = false;
isFixed[num][index] = false;
}
}
// 初始化处理顺序表
for (int num = 1; num <= boardSize; ++num)
{
processList[num - 1].num = num;
processList[num - 1].count = 0;
}
// 读入初始数据
ifstream dataFile("mcnp.in");
for (int rowIndex = 0; rowIndex < boardSize; ++rowIndex)
{
for (int columnIndex = 0; columnIndex < boardSize; ++columnIndex)
{
int temp;
dataFile >> temp;
if (temp)
{
occupy(rowIndex, columnIndex, temp);
isFixed[temp][rowIndex] = true;
++processList[temp - 1].count;
}
}
}
dataFile.close();
// 对处理顺序表进行排序
// 在初始数据中出现次数越多的数字,将越优先处理
sort(processList, processList + boardSize);
}
void print(ostream & resFile);
bool place( const int , const bool );
void process()
{
ofstream resFile("mcnp.out");
bool isPlaced[boardSize] = {false};
int stackTop = 0;
while (stackTop > -1)
{
if (stackTop == boardSize)
{
print(resFile);
--stackTop;
}
else
{
isPlaced[stackTop] = place(processList[stackTop].num,isPlaced[stackTop]);
if (isPlaced[stackTop])
++stackTop;
else
--stackTop;
}
}
resFile.close();
}
bool place( const int num, const bool hasBeenPlacedBefore)
{
int currentRow;
if (!hasBeenPlacedBefore)
{
currentRow = 0;
while ((currentRow < boardSize) && isFixed[num][currentRow]) ++currentRow;
}
else
{
currentRow = boardSize - 1;
while ((currentRow >= 0) && isFixed[num][currentRow]) --currentRow;
}
while (currentRow > -1)
{
if (currentRow == boardSize) return true;
else
{
int& prevColumn = columnInRow[num][currentRow];
int currentColumn = prevColumn + 1;
while (currentColumn < boardSize
&& (isInColumn[num][currentColumn]
|| gameBoard[currentRow][currentColumn] != 0))
++currentColumn;
// 找不到下一个合适的列吗?
if (currentColumn == boardSize)
{
//找不到,释放本行数据,回溯到上一可以修改的行
if (prevColumn > -1)
free(currentRow, prevColumn);
--currentRow;
while ((currentRow >= 0) && isFixed[num][currentRow]) --currentRow;
}
else
{
//找到了,填充新位置,选择下一可以修改的行
if (prevColumn > -1)
free(currentRow, prevColumn);
occupy(currentRow, currentColumn, num);
++currentRow;
while ((currentRow < boardSize) && isFixed[num][currentRow]) ++currentRow;
}
}
}
return false;
}
void print(ostream & resFile)
{
for (int rowIndex = 0; rowIndex < boardSize; ++rowIndex)
{
for (int columnIndex = 0; columnIndex < boardSize; ++columnIndex)
{
resFile << gameBoard[rowIndex][columnIndex] << " ";
}
resFile << endl;
}
resFile << endl;
}
int main()
{
initialize();
process();
return 0;
}