mstc面试题-数独
2006-10-14 15:27 老博客哈 阅读(1576) 评论(1) 收藏 举报前几天学校的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
初始矩阵如上.
好了, 附上我的以行为单位的回溯解法(注意:解不止一组,这里给出一组解就可以了)
 /*
/* 算法思想: 这个算法题目是一个简化的数独问题。我采用的是比较经典的回溯方法,类似九皇后(排除
算法思想: 这个算法题目是一个简化的数独问题。我采用的是比较经典的回溯方法,类似九皇后(排除 斜线的规则)。以行为单位向矩阵中逐个的插入n(n从1到NUM),当然前提是该位置不存在数,且若放置该数
斜线的规则)。以行为单位向矩阵中逐个的插入n(n从1到NUM),当然前提是该位置不存在数,且若放置该数 不会造成冲突,这里冲突的定义是行列存在相同的值。如果存在冲突,则相应的找到正在插入的行上面的具有
不会造成冲突,这里冲突的定义是行列存在相同的值。如果存在冲突,则相应的找到正在插入的行上面的具有 非初始值n的行,并进行回溯操作。
非初始值n的行,并进行回溯操作。
 Author: 农夫三拳(drizzlecrj@gmail.com)
Author: 农夫三拳(drizzlecrj@gmail.com) */
*/
 #include <iostream>
#include <iostream> #include <fstream>
#include <fstream>
 using namespace std;
using namespace std;
 const int NUM = 9;            //矩阵的行数
const int NUM = 9;            //矩阵的行数 int cube[NUM][NUM];            //矩阵的初始排布
int cube[NUM][NUM];            //矩阵的初始排布 int Routine[NUM + 1][NUM];    //对应每一个数字n在每行上的下标数组
int Routine[NUM + 1][NUM];    //对应每一个数字n在每行上的下标数组
 //判断该行是否已经存在数字num,r代表行号
//判断该行是否已经存在数字num,r代表行号 bool IsExistInRow(int r,int num)
bool IsExistInRow(int r,int num) {
{ for(int j = 0; j < NUM; j++)
    for(int j = 0; j < NUM; j++) {
    { if(cube[r][j] == num)
        if(cube[r][j] == num) return true;
            return true; }
    } return false;
    return false; }
}
 //判断该列是否存在数字num,c代表列号
//判断该列是否存在数字num,c代表列号 bool IsExistInColumn(int c,int num)
bool IsExistInColumn(int c,int num) {
{ for(int i = 0; i < NUM; i++)
    for(int i = 0; i < NUM; i++) {
    { if(cube[i][c] == num)
        if(cube[i][c] == num) return true;
            return true; }
    } return false;
    return false; }
}
 //从文件初始读入矩阵并初始化Routine数组
//从文件初始读入矩阵并初始化Routine数组 void Initialize()
void Initialize() {
{ ifstream fin("input.txt");
    ifstream fin("input.txt"); int i, j;
    int i, j; for(i = 0; i < NUM; i++)
    for(i = 0; i < NUM; i++) {
    { for(j = 0; j < NUM; j++)
        for(j = 0; j < NUM; j++) {
        { fin >> cube[i][j];
            fin >> cube[i][j]; }
        } }
    } for(i = 1; i <= NUM; i++)
    for(i = 1; i <= NUM; i++) {
    { for(j = 0; j < NUM; j++)
        for(j = 0; j < NUM; j++) {
        { Routine[i][j] = -1;
            Routine[i][j] = -1; }
        } }
    } }
}
 //打印矩阵
//打印矩阵 void Print()
void Print() {
{ int i, j;
    int i, j; for(i = 0; i < NUM; i++)
    for(i = 0; i < NUM; i++) {
    { for(j = 0; j < NUM - 1; j++)
        for(j = 0; j < NUM - 1; j++) {
        { cout << cube[i][j] << ' ';
            cout << cube[i][j] << ' '; }
        } cout << cube[i][j] << endl;
        cout << cube[i][j] << endl; }
    } }
}
 //核心函数,向矩阵中插入数字n
//核心函数,向矩阵中插入数字n bool FillNum(int n)
bool FillNum(int n) {
{ if( n > NUM)
    if( n > NUM) return true;
        return true; int i, j;
    int i, j; i = j = 0;
    i = j = 0; while(true)
    while(true) {
    { if(i == NUM)
        if(i == NUM) {
        { if(FillNum(n + 1)) //填取下一个数字
            if(FillNum(n + 1)) //填取下一个数字 break;
                break; else
            else   {
            { goto loop;
                goto loop; }
            } }
        } while(i < NUM && IsExistInRow(i, n))//判断i行是否存在该数
        while(i < NUM && IsExistInRow(i, n))//判断i行是否存在该数 i++;
            i++; //如果该行不存在待添加的数字,才进行下面的列检查
        //如果该行不存在待添加的数字,才进行下面的列检查 if(i < NUM)
        if(i < NUM) {
        { while((j < NUM &&  IsExistInColumn(j, n)) || cube[i][j] != 0)//判断j列是否存在该数
            while((j < NUM &&  IsExistInColumn(j, n)) || cube[i][j] != 0)//判断j列是否存在该数 j++;
                    j++; //如果该列不存在待添加的数字,进行记录操作(包括记录Routine,填充矩阵)
            //如果该列不存在待添加的数字,进行记录操作(包括记录Routine,填充矩阵) if(j < NUM)
            if(j < NUM) cube[i][j] = n, Routine[n][i] = j,++i, j = 0;
                cube[i][j] = n, Routine[n][i] = j,++i, j = 0; else
             else {
            { loop:
loop: while(i >= 1 && Routine[n][i-1] == -1)//向上找到初始不存在的该数行号
                while(i >= 1 && Routine[n][i-1] == -1)//向上找到初始不存在的该数行号 i--;
                    i--; //进行回溯操作
                //进行回溯操作 if( i >= 1)
                if( i >= 1) {
                { cube[i - 1][ Routine[n][i - 1] ] = 0;
                    cube[i - 1][ Routine[n][i - 1] ] = 0; j = Routine[n][i - 1] + 1;
                    j = Routine[n][i - 1] + 1; Routine[n][i - 1] = -1;
                    Routine[n][i - 1] = -1; i--;
                    i--; }
                } else if(i <= 0)
                else if(i <= 0) {
                { return false;
                    return false; }
                 } }
            } }
        } }
    } return true;
    return true; }
}
 int main()
int main() {
{ Initialize();
    Initialize(); FillNum(1);
    FillNum(1); Print();
    Print(); cin.ignore();
    cin.ignore();
 return 0;
    return 0; }
}由于不断的填充,后面的数字填入的时候计算量不断减少,所以很快就能出结果了!
如下是一种解法:
9 1 5 8 3 4 6 2 7
8 2 6 1 7 5 3 4 9
1 6 2 7 4 8 5 9 3
6 4 1 3 9 2 8 7 5
2 9 8 4 5 6 7 3 1
3 7 9 2 8 1 4 5 6
5 3 4 9 6 7 2 1 8
7 5 3 6 2 9 1 8 4
4 8 7 5 1 3 9 6 2
后记:
就这么一个小程序,花了我不少时间,什么原因呢?程序写的挺快,找一个bug花了我3个多小时, 结果少了一个if判断,唉, 不过找出来的感觉还是蛮不错的哦!
 
                     
                    
                 
                    
                

 
     
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号