前几天学校的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学长的解稍有不同,是两层回溯,可以求出全部的解,呵呵。
//
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;
}
题目其实就是一个数独(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学长的解稍有不同,是两层回溯,可以求出全部的解,呵呵。























































































































































































