poj 3740 dancing links

題意:

給你一個n*m(n<=16,m<=300)的矩陣。矩陣的每個元素只能是0或1.現在問你能不能從裏面選一些列出來使的沒一列有且僅有一個1.


#include<cstdio>  
#define INF 0x7FFFFFFF  
#define MAXN 90010  
int n, m, size;  
int L[MAXN], R[MAXN], U[MAXN], D[MAXN], H[MAXN]; //H[i] 是i行的頭指針,指向改行的第一個結點   
int C[MAXN],row[MAXN] ,S[MAXN];    //C[i] 是i結點所在的列號 ,row[i]是i結點所在的行,s[i]是i列的結點數量 ;   
void Init() {  
    int i;  
    for (i = 1; i <= n; i++)   
            H[i] = -1;  
    for (i = 0; i <= m; i++) {  
        S[i] = 0;  
        L[i + 1] = i;  
        R[i] = i + 1;  
        U[i] = D[i] = i;  
    }  
    R[m] = 0;  
    size = m + 1;  
}  
void Link(int r, int c) {   //構造十字鏈表   
    U[size] = c;  
    D[size] = D[c];  
    U[D[c]] = size;  
    D[c] = size;  
    if (H[r] < 0)  
        H[r] = L[size] = R[size] = size;  
    else {  
        L[size] = H[r];  
        R[size] = R[H[r]];  
        L[R[H[r]]] = size;  
        R[H[r]] = size;  
    }  
    S[c]++;  
    row[size]=r;
    C[size++] = c;  
}  
void Remove(int c) {   //刪除c列及相應的行   
    int i, j;  
    R[L[c]] = R[c];  
    L[R[c]] = L[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];  
            S[C[j]]--;  
        }  
    }  
}  
void Resume(int c) {  //恢復c列   
    int i, j;  
    R[L[c]] = c;  
    L[R[c]] = c;  
    for (i = D[c]; i != c; i = D[i]) {  
        for (j = R[i]; j != i; j = R[j]) {  
            U[D[j]] = j;  
            D[U[j]] = j;  
            S[C[j]]++;  
        }  
    }  
}  
bool Dance(int now) {   //舞蹈鏈   
    if (R[0] == 0)  //輸出答案   
        return true;  
    int i, j, temp, c;  
    for (temp=INF,i = R[0]; i; i = R[i]) {  
        if(S[i]<temp)  
        {  
            temp=S[i];  
            c=i;  
        }  
    }  
    Remove(c);  
    for(i=D[c];i!=c;i=D[i])  
    {    // ans[now]=row[i]  ;   如果要輸入答案是哪些行 ;   
        for(j=R[i];j!=i;j=R[j])  
            Remove(C[j]);  
        if(Dance(now+1))  
            return true;  
        for(j=L[i];j!=i;j=L[j])  
            Resume(C[j]);  
    }  
    Resume(c);  
    return false;  
}  
int main() {  
    int i, j, k;  
    while (~scanf("%d%d", &n, &m)) {  
        Init();  
        for (i = 1; i <= n; i++) {  
             
            for (j = 1; j <= m; j++) {  
                scanf("%d", &k);  
                if (k)  
                    Link(i, j);  
            }  
        }  
        if (Dance(0))   
            puts("Yes, I found it");  
        else  
            puts("It is impossible");  
    }  
    return 0;  
}  




發佈了218 篇原創文章 · 獲贊 5 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章