【hiho】数独

#define _CRT_SECURE_NO_WARNINGS

#include<vector>
#include<iostream>
#include<cstring>

using namespace std;

struct Node
{
    Node(int x1, int y1) :x(x1), y(y1){}
    int x;
    int y;
    Node* up;
    Node* down;
    Node* left;
    Node* right;
};

class exactCover
{
public:
    vector<int> solveExactCover();
    exactCover(vector<vector<bool>>&);
    vector<int> getAns()
    {
        return ans;
    }

private:
    int M; // Number of rows
    int N; // Number of columns
    Node* mRoot;
    vector<Node*> mColumnLoc;
    vector<int> mColumnCount;
    vector<vector<Node*>> mNodeLoc;
    void cover(int);
    void uncover(int);
    vector<int> ans;
    bool dfs();
};

vector<vector<bool>> Suduko2ExactCover(vector<vector<int>>& a, vector<vector<int>>& list)
{
    vector<vector<bool>> ret;
    int M = 0;
    int N = 81 * 4;
    for (int i = 0; i < 9; i++)
    for (int j = 0; j < 9; j++)
    {
        int st = 1;
        int en = 9;
        if (a[i][j]) st = en = a[i][j];
        for (int k = st; k <= en; k++)
        {
            auto tmp = vector<bool>(N, false);
            tmp[81 * 0 + i * 9 + k - 1] = true;
            tmp[81 * 1 + j * 9 + k - 1] = true;
            tmp[81 * 2 + i * 9 + j] = true;
            tmp[81 * 3 + (i / 3 * 3 + j / 3) * 9 + k - 1] = true;
            ret.push_back(tmp);
            list.push_back(vector<int>{i, j, k});
        }
    }
    return ret;
}

int main()
{

    int T;
    cin >> T;
    while (T--)
    {
        auto a = vector<vector<int>>(9, vector<int>(9, 0));
        vector<vector<int>> list;
        for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9; j++)
            cin >> a[i][j];
        auto para = Suduko2ExactCover(a, list);

        exactCover inst(para);
        inst.solveExactCover();
        auto u = inst.getAns();
        for (auto x : u)
            a[list[x][0]][list[x][1]] = list[x][2];
        for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9; j++)
            cout << a[i][j] << (j == 8 ? "\n" : " ");
    }
    return 0;
}

bool exactCover::dfs()
{
    if (mRoot->right == mRoot) return true;
    auto visitedRow = vector<bool>(M, false);
    auto p = mRoot->right;
    int minC = 100000;
    int miny = -1;
    Node* minp = nullptr;
    while (p != mRoot)
    {
        if (mColumnCount[p->y] < minC)
        {
            minp = p;
            miny = p->y;
            minC = mColumnCount[p->y];
        }
        p = p->right;
    }
    if (!minC || miny == -1) return false;

    bool solved = false;
    p = minp->down;

    cover(miny);

    while (p != minp)
    {
        int currentX = p->x;
        ans.push_back(currentX);

        auto q = p->right;
        while (q != p)
        {
            cover(q->y);
            q = q->right;
        }
        if (!solved)
        if (dfs()) return true;
        q = p->left;
        while (q != p)
        {
            uncover(q->y);
            q = q->left;
        }
        ans.pop_back();
        p = p->down;
    }
    uncover(miny);

    return false;
}

vector<int> exactCover::solveExactCover()
{
    dfs();
    return ans;
}

exactCover::exactCover(vector<vector<bool>>& a)
{
    ans.clear();
    M = a.size();
    if (!M) return;
    N = a[0].size();

    mColumnLoc = vector<Node*>(N, nullptr);
    mColumnCount = vector<int>(N, 0);
    mNodeLoc = vector<vector<Node*>>(M, vector<Node*>(N, 0));
    mRoot = new Node(-1, -1);
    vector<Node*>& cl = mColumnLoc;
    vector<vector<Node*>>& l = mNodeLoc;

    for (int i = 0; i < N; i++) cl[i] = new Node(-1, i);
    mRoot->right = cl[0];
    mRoot->left = cl[N - 1];
    for (int i = 0; i < N; i++)
    {
        cl[i]->left = (i == 0 ? mRoot : cl[i - 1]);
        cl[i]->right = (i == N - 1 ? mRoot : cl[i + 1]);
    }
    for (int i = 0; i < M; i++)
    for (int j = 0; j < N; j++)
    if (a[i][j]) l[i][j] = new Node(i, j);

    for (int j = 0; j < N; j++)
    {
        auto p = cl[j];
        for (int i = 0; i < M; i++)
        if (a[i][j])
        {
            mColumnCount[j]++;
            p->down = l[i][j];
            l[i][j]->up = p;
            p = l[i][j];
        }
        p->down = cl[j];
        cl[j]->up = p;
    }

    for (int i = 0; i < M; i++)
    {
        Node* p = nullptr;
        Node* head = nullptr;
        for (int j = 0; j < N; j++)
        if (a[i][j])
        {
            if (p == nullptr) head = p = l[i][j];
            else
            {
                p->right = l[i][j];
                l[i][j]->left = p;
                p = l[i][j];
            }
        }
        p->right = head;
        head->left = p;
    }
}

void exactCover::cover(int X)
{
    auto head = mColumnLoc[X];

    head->left->right = head->right;
    head->right->left = head->left;
    auto p = head->down;
    while (p != head)
    {
        auto h1 = p;
        auto q = h1->right;
        while (q != h1)
        {
            mColumnCount[q->y]--;
            q->up->down = q->down;
            q->down->up = q->up;
            q = q->right;
        }
        p = p->down;
    }
}

void exactCover::uncover(int X)
{
    auto head = mColumnLoc[X];

    head->left->right = head;
    head->right->left = head;
    auto p = head->up;
    while (p != head)
    {
        auto h1 = p;
        auto q = h1->left;
        while (q != h1)
        {
            mColumnCount[q->y]++;
            q->up->down = q;
            q->down->up = q;
            q = q->left;
        }
        p = p->up;
    }
}

dancing links

网上搜搜就有

特别要注意就是要逆向恢复

不得不说knuth的智商有点高

但是poj上的3074 TLE,我也是不服,各种贴出来说T的数据我都是秒出,算了,不理了

昨天晚上到今天纠结一个小错误

类里面的成员数据不初始化的话 有可能不是0的

就这个小错耗了N小时,让我发了两条朋友圈

时间: 2024-08-04 10:43:43

【hiho】数独的相关文章

hihoCoder #1321 : 搜索五?数独 (Dancing Links ,精确覆盖)

hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. 提示已经讲解的很清楚了.稍微整理下思路.最后附AC代码. 一.Dancing Links解决精确覆盖问题.      1.精确覆盖问题         给定一个n行,m列的01矩阵.从中选择若干行使得每一列有且恰好只有一个1. 例如: 答案是选择2,3,4行. 2.DancingLinks求解精确

第二次作业——个人项目实战:数独

1.阅读 刚开始泛看<构建之法>的时候,还是觉得非常难理解里面的内容,特别是代码部分.后来第二次拿起这本书,从第一章开始看起,慢慢了解了"软件企业=软件+商业模式"和对软件工程的定义,但是更多地还是记忆了一遍,没有明白这里面的深意:看第二章的时候,跟着单元测试.回归测试的.效能分析的内容自己照着书上的代码敲了一敲,偶尔会出现bug,但是能得到书上所说的效果还是很开心的,效能分析,感觉就是代码的效率问题,追求高效,然后接触到了软件工程师的一套模型-个人开发流程PSP,我也尝试

洛谷 【P1074】靶形数独

P1074 靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格 高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字.每

#计算机#数独

数独是一项益智小游戏,规则简单易懂,但内容千变万化.这次我想要研究的是用java编程实现解数独和数独题目的生成.首先要弄清数独的游戏规则:在一个9×9的方格中分布着1-9的数字和空格,玩家在空格中填写适当的数字,使得每行.每列.9个3×3的方格中数字1-9均只出现一次. 对于解数独初步构思的时候我产生了两种想法: 第一种想法利用计算机强大的运算能力,遍历当前空格所有可以填入的数字,向后递归,当某个空格不能填入数字,而空格数不为零时返回上一步.如果某一步只能填入一个确定的数字,可以把这一步优先填好

安卓旅途之——开发数独(一)

安卓旅途之——开发数独(一) 数独游戏简介 数独游戏,是一种数学智力拼图游戏,是“独立的数字游戏”的简称,源自18世纪末的瑞士,后在美国发展,在日本得以发扬光大. 数独游戏可以训练玩家的逻辑推理能力,不少教育者皆认为数独是锻炼脑筋的好方法. 其规则如下: 1.游戏会从一个部分带有数字的九宫格开始. 在9×9的大九宫格(即3格宽×3格高)方阵里,每一格又细分为一个小九宫格. 2.游戏开始,已给定若干数字,其它宫位留白,玩家需要自己按照逻辑推敲出剩下的空格里是什么数字. 3.填数字时必须满足以下条件

使用AxureRP7.0制作经典数独小游戏原型,axure游戏原型下载

之前,有同学在Q群中提问,如何使用axure制作经典数独解谜小游戏,当时由于时间关系没有来得及亲手制作,而是给同学们提供了Axure6.5版本的一个数独解谜游戏的原型,本教程由axure原型库网站录制,转载请注明出处!但是那个原型做的太过繁杂,所以仅供大家参考交流:在此,金乌老师特地抽时间给同学们使用AxureRP7.0制作了一下,感觉对实战逻辑分析和axure变量的掌握比较有考验,所以就放出来供大家学习交流使用. 在学习的过程中,如果你仅凭自己现有的对axure的掌握,无法准确分析并组织出原型

洛谷—— P1784 数独

https://www.luogu.org/problem/show?pid=1784 题目描述 数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复.每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的. 芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战. 这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”. 据介绍,目前数独游戏的难度的

HDU 1426 Sudoku Killer【DFS 数独】

自从2006年3月10日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视. 据说,在2008北京奥运会上,会将数独列为一个单独的项目进行比赛,冠军将有可能获得的一份巨大的奖品———HDU免费七日游外加lcy亲笔签名以及同hdu acm team合影留念的机会. 所以全球人民前仆后继,为了奖品日夜训练茶饭不思.当然也包括初学者linle,不过他太笨了又没有多少耐性,只能做做最最基本的数独题,不过他还是想得到那些奖品,你能帮帮他吗?你只要把答案告诉他就可以,不用教他是怎么做的

[NOIP2009] 靶形数独

[NOIP2009] 靶形数独 传送门 题目 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的) .在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1到 9 的