hdu 1426——Dancing links

这篇博客介绍了如何运用Dancing links算法解决HDU 1426题目,博主通过自学并总结了算法的核心部分,提供了一个Dancing links的模板,并附带了完整的C++代码实现。
摘要由CSDN通过智能技术生成
最近在学Dancing links 然后问学长。。。被骂- -
“这么简单都不会啊!!!自己慢慢学。。。什么都要人教的啊。。。那你以后怎么办啊!!!”
好吧~然后。。自学了。。。
自己各种理解后总结的。。。断断续续地花了一个下午。
这个就是以后Dacing links的模板了。。。吼吼吼吼~


<code>

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

#define INF 1000000000
const int N = 9;
const int head = 0;
const int mn = N * N * N *(N * N * N * 4) + N;
const int nn = N * N * N + N;
int U[mn], D[mn], L[mn], R[mn];
int C[mn], Row[mn];
int H[nn], Q[nn], S[nn], vis[nn], size;
int a[nn][nn], ans[nn][nn];


void prepare(int r, int c) {
    int i;
    for (i = 0; i <= c; i++) {
        S[i] = 0; //当前列元素个数
        U[i] = D[i] = i;
        R[i] = i + 1;
        L[i + 1] = i;
    }
    R[c] = 0;
    size = c;
    while (r) {
        H[r--] = -1;
    }
}

void place(int &r, int &c1, int &c2, int &c3, int &c4, int i, int j, int k) {
    r = (i * N + j) * N + k; //行号
    //四个列号
    c1 = i * N + j + 1; //表示位于第i行j列的格子的列
    c2 = N * N + i * N + k; //表示在第i行填k这个数字的列
    c3 = 2 * N * N + j * N + k; //表示在第j列填k这个数字的列
    c4 = 3 * N * N + ((i / 3) * 3 + j / 3) * N + k; //表示3*3格子中填k这个数字的列
}

void link(int r, int c) {
    size++; //r行c列的值编号为size
    C[size] = c;
    S[c]++;
    Row[size] = r;
    D[size] = D[c];
    U[D[c]] = size;
    U[size] = c;
    D[c] = size;
    if (H[r] < 0) {
        H[r] = size;
        L[size] = size;
        R[size] = size;
    } else {
        R[size] = R[H[r]];
        L[R[H[r]]] = size;
        L[size] = H[r];
        R[H[r]] = size;
    }
}

void remove(const int &cur) {
    L[R[cur]] = L[cur];
    R[L[cur]] = R[cur];
    for (int i = D[cur]; i != cur; i = D[i]) {
        for (int j = R[i]; j != i; j = R[j]) {
            U[D[j]] = U[j];
            D[U[j]] = D[j];
            --S[C[j]];
        }
    }
}

void resume(const int &cur) {
    for (int i = U[cur]; i != cur; i = U[i]) {
        for (int j = L[i]; j != i; j = L[j]) {
            ++S[C[j]];
            U[D[j]] = j;
            D[U[j]] = j;
        }
    }
    L[R[cur]] = cur;
    R[L[cur]] = cur;
}

bool dance(int cur) {
    int i, j, c, temp;
    if (R[head] == head) {
        for (i = 0; i < cur; i++) {
            int x = (Row[Q[i]] - 1) / N / N;
            int y = (Row[Q[i]] - 1) / N % N;
            ans[x][y] = (Row[Q[i]] - 1) % N + 1;
        }
        return true;
    }
    temp = INF;
    for (i = R[0]; i != 0; i = R[i])
        if (S[i] < temp) {
            temp = S[i];
            c = i;
        }
    remove(c);
    for (i = D[c]; i != c; i = D[i]) {
        Q[cur] = i;
        for (j = R[i]; j != i; j = R[j])
            remove(C[j]);
        if (dance(cur + 1))
            return true;
        for (j = L[i]; j != i; j = L[j])
            resume(C[j]);
    }
    resume(c);
    return false;
}

int init() {
    int i, j, k, r, c1, c2, c3, c4;
    char temp[5];

    //Input begin
    if (scanf("%s", temp) != 1)
        return 0;
    a[0][0] = (temp[0] == '?' ? 0 : temp[0] - '0');
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++) {
            if (!i && !j)
                continue;
            scanf("%s", temp);
            a[i][j] = (temp[0] == '?' ? 0 : temp[0] - '0');
        }
    //Input end

    prepare(N * N * N, N * N * 4);

    memset(vis, 0, sizeof (vis));
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            if (a[i][j]) {
                place(r, c1, c2, c3, c4, i, j, a[i][j]);
                link(r, c1), link(r, c2), link(r, c3), link(r, c4);
                vis[c2] = vis[c3] = vis[c4] = 1; //记录下该列是否已经有了
            }
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            if (!a[i][j]) {//对于没有填的进行建图
                for (k = 1; k <= N; k++) {
                    place(r, c1, c2, c3, c4, i, j, k);
                    if (vis[c2] || vis[c3] || vis[c4])
                        continue;
                    link(r, c1), link(r, c2), link(r, c3), link(r, c4);
                }
            }
    return 1;
}

void printresult() {
    int i, j;
    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) {
            if (j) {
                printf(" ");
            }
            printf("%d", ans[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int t = 0;
    while (init()) {
        dance(head);
        if (t++)
            printf("\n");
        printresult();
    }
    return 0;
}





</code>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值