码迷,mamicode.com
首页 > 其他好文 > 详细

【hiho】数独

时间:2016-06-15 16:01:21      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

#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小时,让我发了两条朋友圈

【hiho】数独

标签:

原文地址:http://www.cnblogs.com/soya/p/5587620.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!