程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3740 DLX

POJ 3740 DLX

編輯:C++入門知識

題意:給你一個01矩陣,然後求是否存在選擇一些行,使得每一列的1的個數都為1。 思路:貌似樸素的DFS也可以,加點剪枝就可以過。這裡貼個DLX的模版。   這裡講的很詳細。

#include <set>  
#include <map>  
#include <stack>  
#include <cmath>  
#include <queue>  
#include <cstdio>  
#include <string>  
#include <vector>  
#include <iomanip>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
#define Max 2505  
#define FI first  
#define SE second  
#define ll long long  
#define PI acos(-1.0)  
#define inf 0x3fffffff  
#define LL(x) ( x << 1 )  
#define bug puts("here")  
#define PII pair<int,int>  
#define RR(x) ( x << 1 | 1 )  
#define mp(a,b) make_pair(a,b)  
#define mem(a,b) memset(a,b,sizeof(a))  
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )  
  
using namespace std;  
  
#define N 5555  
  
///DLX  
int L[N] , R[N] , D[N] , U[N] ,S[N] , C[N] ,st[N] ;//S[] 表示這一列的點數。C[] 表示這個點位於那一列。  
int n , m , num , head ;  
  
void insert(int col , int pos){//在這一列插入序號為pos的點  
    int now = col ;  
    while(D[now] != col) now = D[now] ;  
    D[now] = pos ;  
    D[pos] = col ;  
    U[pos] = now ;  
    U[col] = pos ;  
}  
  
void init(){  
    head = 0 ;  
    R[head] = 1 ;L[head] = m ;  
    for (int i = 1 ; i <= m ; i ++ ){//每一行的頭指針  
        if(i == 1)L[i] = head ;  
        else L[i] = i - 1 ;  
        if(i == m)R[i] = head ;  
        else R[i] = i + 1 ;  
        U[i] = i ;  
        D[i] = i ;  
        S[i] = 0 ;  
        C[i] = i ;  
    }  
    num = m ;//已經插入m個節點  
    int k ;  
    for (int i = 1 ; i <= n ; i ++ ){  
        mem(st ,0) ;  
        for (int j = 1 ; j <= m ; j ++ ){  
            scanf("%d",&k) ;  
            if(!k)continue ;  
            num ++ ;  
            insert(j , num) ;  
            if(st[0] == 0){//每行的第一個  
                L[num] = num ; R[num] = num ;  
            }else{  
                L[num] = st[st[0]] ;  
                R[num] = st[1] ;  
                R[st[st[0]]] = num ;  
                L[st[1]] = num ;  
            }  
            st[++st[0]] = num ;  
            C[num] = j ;  
            S[j] ++ ;  
        }  
    }  
}  
  
void remove(const int &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] ;  
            -- S[C[j]] ;  
        }  
    }  
}  
  
void resume(const int &c){//恢復  
    for (int i = U[c] ; i != c ; 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[c]] = c ;  
    R[L[c]] = c ;  
}  
  
int dfs(const int &k){  
    if(R[head] == head)return 1 ;  
    int MX = inf ,c ;  
    for (int t = R[head] ; t != head ; t = R[t]){//找出點最少的一列  
        if(S[t] < MX){  
            MX = S[t] ;  
            c = t ;  
        }  
    }  
    remove(c) ;  
    for (int i = D[c] ; i != c ; i = D[i]){  
        for (int j = R[i] ; j != i ; j = R[j]){  
            remove(C[j]) ;  
        }  
        if(dfs(k + 1))return 1 ;  
        for (int j = L[i] ; j != i ; j = L[j]){  
            resume(C[j]) ;  
        }  
    }  
    resume(c) ;  
    return 0 ;  
}  
int main() {  
    while(cin >> n >> m){  
        init() ;  
        if(dfs(0))puts("Yes, I found it") ;  
        else puts("It is impossible") ;  
    }  
    return 0 ;  
}  

 


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved