kuangbin三Dancing Links合集

Dancing Links,跳舞鏈,是一種數據結構以及配套的算法,用於解決精確覆蓋問題與重複覆蓋問題。具體講解博客鏈接:
https://www.cnblogs.com/grenet/p/3145800.html
https://www.cnblogs.com/wujiechao/p/5767124.html

ZOJ3029 Treasure Map:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
typedef long long ll;
using namespace std;

const int MAXN = 500010;
const int MAX = 510;
const int MAXM = 1010;

struct DancingLinks
{
    int n, m;
    int U[MAXN], D[MAXN], L[MAXN], R[MAXN];
    int row[MAXN], col[MAXN];
    int rowHead[MAX], nodeNumOfCol[MAXM];
    int ansd, nodeNum;

    void init(int _n, int _m)
    {
        n = _n;
        m = _m;
        for(int i = 0; i <= m; i++)
        {
            nodeNumOfCol[i] = 0;
            U[i] = D[i] = i;
            L[i] = i - 1;
            R[i] = i + 1;
        }
        R[m] = 0; L[0] = m;
        nodeNum = m;
        for(int i = 1; i <= n; i++)
            rowHead[i] = -1;
    }

    void push(int r, int c)
    {
        ++nodeNumOfCol[col[++nodeNum] = c];
        row[nodeNum] = r;
        D[nodeNum] = D[c];
        U[D[c]] = nodeNum;
        U[nodeNum] = c;
        D[c] = nodeNum;
        if(rowHead[r] < 0)
            rowHead[r] = R[nodeNum] = L[nodeNum] = nodeNum;
        else
        {
            R[nodeNum] = R[rowHead[r]];
            L[R[rowHead[r]]] = nodeNum;
            L[nodeNum] = rowHead[r];
            R[rowHead[r]] = nodeNum;
        }
    }

    void del(int c)//刪除第c列及其節點所在的行
    {
        L[R[c]] = L[c]; R[L[c]] = R[c];
        for(int i = D[c]; i != c; i = D[i])
            for(int j = R[i]; j != i; j = R[j])
            {
                U[D[j]] = U[j];
                D[U[j]] = D[j];
                --nodeNumOfCol[col[j]];
            }
    }

    void reback(int c)//恢復第c列及其節點所在行
    {
        for(int i = U[c]; i != c; i = U[i])
            for(int j = L[i]; j != i; j = L[j])
                ++nodeNumOfCol[col[U[D[j]] = D[U[j]] = j]];
       L[R[c]] = R[L[c]] = c;
    }

    void Dance(int d)
    {
        if(ansd != -1 && ansd <= d) return;
        if(R[0] == 0)
        {
            if(ansd == -1)
                ansd = d;
            else if(d < ansd)
                ansd = d;
            return;
        }
        int c = R[0];
        for(int i = R[0]; i != 0; i = R[i])
            if(nodeNumOfCol[i] < nodeNumOfCol[c])
                c = i;
        del(c);
        for(int i = D[c]; i != c; i = D[i])
        {
            for(int j = R[i]; j != i; j = R[j])
                del(col[j]);
            Dance(d+1);
            for(int j = L[i]; j != i; j = L[j])
                reback(col[j]);
        }
        reback(c);
    }
};
DancingLinks dlx;

int main()
{
    int t;
    int n, m, p;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %d %d", &n, &m, &p);
        dlx.init(p, n*m);
        int x1, y1, x2, y2;
        for(int e = 1; e <= p; e++)
        {
            scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
            for(int i = x1+1; i <= x2; i++)
                for(int j = y1+1; j <= y2; j++)
                    dlx.push(e, j+(i-1)*m);
        }
        dlx.ansd = -1;
        dlx.Dance(0);
        printf("%d\n", dlx.ansd);
    }
    return 0;
}

HDU2295 Radar:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
typedef long long ll;
using namespace std;

const int maxnode = 3000;
const int MaxM = 55;
const int MaxN = 55;

struct DLX
{
    int n, m, nodeNum;
    int U[maxnode], D[maxnode], R[maxnode], L[maxnode];
    int Row[maxnode], Col[maxnode];
    int H[MaxN], S[MaxN];
    int ands, ans[MaxN];
    int K;

    void init(int _n, int _m)
    {
        n = _n;
        m = _m;
        for(int i = 0; i <= m; i++)
        {
            S[i] = 0;
            U[i] = D[i] = i;
            L[i] = i-1;
            R[i] = i+1;
        }
        R[m] = 0; L[0] = m;
        nodeNum = m;
        for(int i = 1; i <= n; i++)
            H[i] = -1;
    }

    void push(int r, int c)
    {
        ++S[Col[++nodeNum] = c];
        Row[nodeNum] = r;
        D[nodeNum] = D[c];
        U[D[c]] = nodeNum;
        U[nodeNum] = c;
        D[c] = nodeNum;
        if(H[r] < 0) H[r] = L[nodeNum] = R[nodeNum] = nodeNum;
        else
        {
            R[nodeNum] = R[H[r]];
            L[R[H[r]]] = nodeNum;
            L[nodeNum] = H[r];
            R[H[r]] = nodeNum;
        }
    }

    void del(int c)
    {
        for(int i = D[c]; i != c; i = D[i])
            L[R[i]] = L[i], R[L[i]] = R[i];
    }

    void reback(int c)
    {
        for(int i = U[c]; i != c; i = U[i])
            L[R[i]] = R[L[i]] = i;
    }

    bool v[maxnode];
    int f() //評估函數
    {
        int ret = 0;
        for(int e = R[0]; e != 0; e = R[e]) v[e] = true;
        for(int e = R[0]; e != 0; e = R[e])
            if(v[e])
            {
                ret++;
                v[e] = false;
                for(int i = D[e]; i != e; i = D[i])
                    for(int j = R[i]; j != i; j = R[j])
                        v[Col[j]] = false;
            }
        return ret;
    }

    bool Dance(int d)
    {
        if(d + f() > K) return false; //用評估函數剪枝
        if(R[0] == 0) return d <= K;
        int c = R[0];
        for(int i = R[0]; i != 0; i = R[i])
            if(S[i] < S[c])
                c = i;
        for(int i = D[c]; i != c; i = D[i])
        {
            del(i);
            for(int j = R[i]; j != i; j = R[j]) del(j);
            if(Dance(d+1)) return true;
            for(int j = L[i]; j != i; j = L[j]) reback(j);
            reback(i);
        }
        return false;
    }
};
DLX g;

struct point
{
    int x, y;
    void input()
    {
        scanf("%d %d", &x, &y);
    }
}city[MaxN], Radar[MaxM];

double dis(point a, point b)
{
    return
        sqrt((double)(a.x-b.x)*(a.x-b.x) + (double)(a.y-b.y)*(a.y-b.y));
}

const double eps = 1e-8;

int main()
{
    int t;
    int n, m;
    int k;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %d %d", &n, &m, &k);
        for(int i = 0; i < n; i++) city[i].input();
        for(int i = 0; i < m; i++) Radar[i].input();
        g.K = k;
        double l = 0, r = 5000;
        while(r-l >= eps)
        {
            double mid = (l+r)/2;
            g.init(m, n);
            for(int i = 0; i < m; i++)
                for(int j = 0; j < n; j++)
                    if(dis(Radar[i], city[j]) < mid - eps)
                        g.push(i+1, j+1);
            if(g.Dance(0)) r = mid-eps;
            else l = mid+eps;
        }
        printf("%.6f\n", l);
    }
    return 0;
}

FZU1686 神龍的難題:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
typedef long long ll;
using namespace std;

const int maxnode = 15*15*15*15+100;
const int MaxM = 15*15+10;
const int MaxN = 15*15+10;
const int INF = 0x3f3f3f3f;

struct DLX
{
    int n, m, nodeNum;
    int U[maxnode], D[maxnode], R[maxnode], L[maxnode];
    int Row[maxnode], Col[maxnode];
    int H[MaxN]/*每行的頭指針*/, S[MaxN]/*每列的節點個數*/;
    int ansd;

    void init(int _n, int _m)
    {
        n = _n;
        m = _m;
        for(int i = 0; i <= m; i++)
        {
            S[i] = 0;
            U[i] = D[i] = i;
            L[i] = i-1;
            R[i] = i+1;
        }
        R[m] = 0; L[0] = m;
        nodeNum = m;
        for(int i = 1; i <= n; i++)
            H[i] = -1;
    }

    void push(int r, int c)
    {
        ++S[Col[++nodeNum] = c];
        Row[nodeNum] = r;
        D[nodeNum] = D[c];
        U[D[c]] = nodeNum;
        U[nodeNum] = c;
        D[c] = nodeNum;
        if(H[r] < 0) H[r] = L[nodeNum] = R[nodeNum] = nodeNum;
        else
        {
            R[nodeNum] = R[H[r]];
            L[R[H[r]]] = nodeNum;
            L[nodeNum] = H[r];
            R[H[r]] = nodeNum;
        }
    }

    void del(int c)
    {
        for(int i = D[c]; i != c; i = D[i])
            L[R[i]] = L[i], R[L[i]] = R[i];
    }

    void reback(int c)
    {
        for(int i = U[c]; i != c; i = U[i])
            L[R[i]] = R[L[i]] = i;
    }

    bool v[maxnode];
    int f() //評估函數
    {
        int ret = 0;
        for(int e = R[0]; e != 0; e = R[e]) v[e] = true;
        for(int e = R[0]; e != 0; e = R[e])
            if(v[e])
            {
                ret++;
                v[e] = false;
                for(int i = D[e]; i != e; i = D[i])
                    for(int j = R[i]; j != i; j = R[j])
                        v[Col[j]] = false;
            }
        return ret;
    }

    void Dance(int d)
    {
        if(d + f() >= ansd) return; //用評估函數剪枝
        if(R[0] == 0)
        {
            if(d < ansd) ansd = d;
            return;
        }
        int c = R[0];
        for(int i = R[0]; i != 0; i = R[i])
            if(S[i] < S[c])
                c = i;
        for(int i = D[c]; i != c; i = D[i])
        {
            del(i);
            for(int j = R[i]; j != i; j = R[j]) del(j);
            Dance(d+1);
            for(int j = L[i]; j != i; j = L[j]) reback(j);
            reback(i);
        }
    }
};
DLX g;

int Map[20][20];

int main()
{
    int n, m, n1, m1;
    while(~scanf("%d %d", &n, &m))
    {
        memset(Map, 0, sizeof(Map));
        int num, cnt = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
            {
                scanf("%d", &num);
                if(num == 1) Map[i][j] = (++cnt);
                else Map[i][j] = 0;
            }
        g.init(n*m, cnt);
        cnt = 1; //row
        scanf("%d %d", &n1, &m1);
        for(int i = 0; i < n-n1+1; i++)
            for(int j = 0; j < m-m1+1; j++)
            {
                for(int e = i; e < i+n1; e++)
                    for(int k = j; k < j+m1; k++)
                        if(Map[e][k])
                            g.push(cnt, Map[e][k]);
                cnt++;
            }
        g.ansd = INF;
        g.Dance(0);
        printf("%d\n", g.ansd);
    }
    return 0;
}

POJ3074 Sudoku:https://blog.csdn.net/baidu_29410909/article/details/51289650
目前作爲模板儲存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章