HDU 1426 Sudoku Killer

HDU 1426 Sudoku Killer

题意:

题意很简单啦。就是填数独,数独的规则是每行每列,每个3 * 3的格子必须有1-9构成且只能使用这些数字有且仅有一次

思路

dfs嘛,很明显的搜索题目,要注意的就是判断3 * 3格子的一个技巧,通过简单的四则元算就能确定数字所在的位置。保存?所在的地方到vector中,递归停止条件为填的数字已经和?的个数一样了,不用设置vis标记数组,统一通过check函数检查是否符合条件。dfs调用完成以后,如果返回false 应该把刚刚填上的数字重新设置为?,表示刚刚这种方式不行。如果返回true,则继续返回true,因为返回true当且仅当整个数独填写完成,所以一直往上回朔即可。

代码:

struct Point
{
    Point(int x, int y)
        : x(x), y(y) {}
    int x, y;
};
char sudoku[9][9];
vector<Point>v;

bool check(int x, int y, int num)
{
    for(int i = 0; i < 9; ++i)
        if(num + '0' == sudoku[x][i] && i != y)
            return false;
        else if(num + '0' == sudoku[i][y] && i != x)
            return false;
    for(int i = x / 3 * 3; i < x / 3 * 3 + 3; ++i)    //通过 / 3 * 3确定3 * 3格子的位置
        for(int j = y / 3 * 3; j < y / 3 * 3 + 3; ++j)
            if(sudoku[i][j] == num + '0' && i != x && j != y)
            {
                return false;
            }
    return true;
}

bool dfs(int pos)
{
    if(pos == v.size())
    {
        return true;
    }
    for(int i = 1; i <= 9; ++i)
    {
        if(check(v[pos].x, v[pos].y, i))
        {
            sudoku[v[pos].x][v[pos].y] = i + '0';   //选上这个数字
            if(dfs(pos + 1))
                return true;
            sudoku[v[pos].x][v[pos].y] = '?';     //放弃选的数字
        }
    }
    return false;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // LOCAL
    bool first = true;
    ios::sync_with_stdio(false);    //关闭同步,加快速度
    while(cin >> sudoku[0][0])
    {
        v.clear();
        if(sudoku[0][0] == '?')
            v.emplace_back(0, 0);
        for(int i = 0; i < 9; ++i)
            for(int j = 0; j < 9; ++j)
                if(i == 0 && j == 0)
                    continue;
                else
                {
                    cin >> sudoku[i][j];
                    if(sudoku[i][j] == '?')
                        v.emplace_back(i, j);
                }
        dfs(0);
        if(!first)
            cout << endl;
        first = false;
        for(int i = 0; i < 9; ++i)
        {
            cout << sudoku[i][0];
            for(int j = 1; j < 9; ++j)
                cout << " " << sudoku[i][j];
            cout << endl;
        }

    }
    return 0;
}

一组数据(Ubuntu Sudoku游戏 中等难度随机生成的):

?    ?    9    ?    ?    5    2    ?    ?
?    8    ?    ?    9    ?    1    7    ?
4    ?    ?    ?    ?    3    ?    6    5
?    3    ?    5    ?    2    4    9    ?
?    ?    ?    ?    6    ?    ?    ?    ?
?    2    7    8    ?    4    ?    5    ?
6    1    ?    3    ?    ?    ?    ?    9
?    5    8    ?    2    ?    ?    1    ?
?    ?    3    6    ?    ?    7    ?    ?

答案:

1    6    9    7    4    5    2    8    3
3    8    5    2    9    6    1    7    4
4    7    2    1    8    3    9    6    5
8    3    6    5    1    2    4    9    7
5    4    1    9    6    7    8    3    2
9    2    7    8    3    4    6    5    1
6    1    4    3    7    8    5    2    9
7    5    8    4    2    9    3    1    6
2    9    3    6    5    1    7    4    8

GIF动态演示:(黄色表示需要填写,红色表示回朔时将数字重新设置为?)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gscsdlz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值