zoukankan      html  css  js  c++  java
  • UVA 387 A Puzzling Problem

    UVA_387

        由于是精确覆盖问题,所以可以用Dancing Links去解决,只是需要把每个拼图按摆放位置的不同分成若干个拼图,但这些拼图都属于一类的,这一点要在Dancing Links的列中体现出来。

    #include<stdio.h>
    #include<string.h>
    #define MAXM 6
    #define INF 0x3f3f3f3f
    const int MAXN = 6 * 6;
    const int MAXD = 6 * 6 * 6 * (6 * 6 + 6) + 6 * 6 + 6;
    char b[MAXM];
    int N = 4, M, ans[MAXM][MAXM], g[MAXM][MAXM][MAXM], x[MAXM], y[MAXM];
    int size, U[MAXD], D[MAXD], L[MAXD], R[MAXD], S[MAXN], H[MAXD], X[MAXD], C[MAXD], Q[MAXD];
    int st[MAXD], sx[MAXD], sy[MAXD];
    void prepare(int r, int c)
    {
    int i;
    for(i = 0; i <= c; i ++)
    {
    L[i + 1] = i, R[i] = i + 1;
    S[i] = 0;
    U[i] = D[i] = i;
    }
    R[c] = 0;
    size = c;
    while(r)
    H[r --] = -1;
    }
    void insert(int r, int c)
    {
    ++ size;
    X[size] = r;
    C[size] = c;
    ++ S[c];
    U[size] = c;
    D[size] = D[c];
    U[D[c]] = size;
    D[c] = size;
    if(H[r] == -1)
    H[r] = L[size] = R[size] = size;
    else
    {
    R[size] = R[H[r]];
    L[size] = H[r];
    L[R[H[r]]] = size;
    R[H[r]] = size;
    }
    }
    void init()
    {
    int i, j, k, p, q, row;
    prepare(N * N * M, N * N + M);
    row = 0;
    for(i = 1; i <= M; i ++)
    {
    scanf("%d%d", &x[i], &y[i]);
    for(j = 0; j < x[i]; j ++)
    {
    scanf("%s", b);
    for(k = 0; k < y[i]; k ++)
    g[i][j][k] = b[k] - '0';
    }
    for(j = 0; j + x[i] <= N; j ++)
    for(k = 0; k + y[i] <= N; k ++)
    {
    ++ row;
    st[row] = i, sx[row] = j, sy[row] = k;
    insert(row , i);
    for(p = 0; p < x[i]; p ++)
    for(q = 0; q < y[i]; q ++)
    if(g[i][p][q])
    insert(row, (j + p) * N + (k + q) + M + 1);
    }
    }
    }
    void remove(int c)
    {
    int i, j;
    L[R[c]] = L[c];
    R[L[c]] = R[c];
    for(i = D[c]; i != c; i = D[i])
    for(j = R[i]; j != i; j = R[j])
    {
    U[D[j]] = U[j];
    D[U[j]] = D[j];
    }
    }
    void resume(int c)
    {
    int i, j;
    for(i = U[c]; i != c; i = U[i])
    for(j = L[i]; j != i; j = L[j])
    {
    U[D[j]] = j;
    D[U[j]] = j;
    }
    L[R[c]] = c;
    R[L[c]] = c;
    }
    int dance(int cur)
    {
    int i, j, min, c;
    if(!R[0])
    {
    int k, row, p, q;
    for(i = 0; i < cur; i ++)
    {
    row = Q[i];
    k = st[row];
    for(p = 0; p < x[k]; p ++)
    for(q = 0; q < y[k]; q ++)
    if(g[k][p][q])
    ans[p + sx[row]][q + sy[row]] = k;
    }
    return 1;
    }
    min = INF;
    for(i = R[0]; i != 0; i = R[i])
    if(S[i] < min)
    {
    min = S[i];
    c = i;
    }
    remove(c);
    for(i = D[c]; i != c; i = D[i])
    {
    Q[cur] = X[i];
    for(j = R[i]; j != i; j = R[j])
    remove(C[j]);
    if(dance(cur + 1))
    return 1;
    for(j = L[i]; j != i; j = L[j])
    resume(C[j]);
    }
    resume(c);
    return 0;
    }
    void solve()
    {
    int i, j;
    if(dance(0))
    {
    for(i = 0; i < N; i ++)
    {
    for(j = 0; j < N; j ++)
    printf("%d", ans[i][j]);
    printf("\n");
    }
    }
    else
    printf("No solution possible\n");
    }
    int main()
    {
    int t = 0;
    for(;;)
    {
    scanf("%d", &M);
    if(!M)
    break;
    if(t ++)
    printf("\n");
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    jvm05
    jvm04
    jvm03
    jvm02
    jvm01
    rabbitmq-01
    lock接口认识及可重入锁的实现
    volitile的使用
    自旋锁,死锁与重入锁
    上机实验4--求序列的最大元素和最小元素
  • 原文地址:https://www.cnblogs.com/staginner/p/2298785.html
Copyright © 2011-2022 走看看