FZU 1686 dlx重复覆盖

  1 #include <iostream>

  2 #include <cstring>

  3 #include <cstdio>

  4 #include <algorithm>

  5 #include <queue>

  6 #include <climits>

  7 #include <cmath>

  8 

  9 using namespace std;

 10 #define N 230

 11 #define MAXNODE 60000

 12 const int INF = INT_MAX;

 13 const double eps = 1e-8;

 14 

 15 int n,m,n1,m1;

 16 

 17 struct DLX{

 18     int n,m,size;

 19     int U[MAXNODE] , D[MAXNODE] , L[MAXNODE] , R[MAXNODE];

 20     int col[MAXNODE] , row[MAXNODE];

 21     int first[N] , cnt_col[N] , ans;

 22     bool v[MAXNODE];

 23 

 24     void init(int _n , int _m)

 25     {

 26         n = _n , m = _m , size = _m;

 27         for(int i=0 ; i<=m ; i++){

 28             U[i] = D[i] = i;

 29             L[i] = i-1 , R[i] = i+1;

 30             col[i] = i , row[i] = 0;

 31         }

 32         L[0] = m , R[m] = 0;

 33         for(int i=1 ; i<=n ; i++) first[i] = -1;

 34         for(int i=1 ; i<=m ; i++) cnt_col[i] = 0;

 35         ans = INF;

 36     }

 37 

 38     void link(int r , int c)

 39     {

 40         ++size;

 41         U[D[c]] = size , D[size] = D[c];

 42         U[size] = c , D[c] = size;

 43         cnt_col[c]++;

 44 

 45         if(first[r]<0) first[r] = L[size] = R[size] = size;

 46         else{

 47             R[size] = R[first[r]] , L[R[first[r]]] = size;

 48             L[size] = first[r] , R[first[r]] = size;

 49         }

 50         row[size] = r , col[size] = c;

 51     }

 52 

 53     void Remove(int c)

 54     {

 55         for(int i=D[c] ; i!=c ; i=D[i]){

 56             L[R[i]] = L[i] , R[L[i]] = R[i];

 57         }

 58     }

 59 

 60     void Resume(int c)

 61     {

 62         for(int i=U[c] ; i!=c ; i=U[i]){

 63             L[R[i]] = R[L[i]] = i;

 64         }

 65     }

 66 

 67     int f()

 68     {

 69         int ret = 0;

 70         for(int c=R[0] ; c!=0 ; c=R[c]) v[c]=true;

 71         for(int c=R[0] ; c!=0 ; c=R[c])

 72             if(v[c]){

 73                 ret++;

 74                 v[c] = false;

 75                 for(int i=D[c] ; i!=c ; i=D[i])

 76                     for(int j=R[i] ; j!= i ; j=R[j])

 77                         v[col[j]]=false;

 78             }

 79         return ret;

 80     }

 81 

 82     void Dance(int d)

 83     {

 84         if(d+f() >= ans) return;

 85         if(!R[0]){

 86             ans = min(ans , d);

 87             return;

 88         }

 89         int st = R[0];

 90         for(int i=R[0] ; i!=0 ; i=R[i])

 91             if(cnt_col[st]>cnt_col[i]) st=i;

 92 

 93         for(int i=D[st] ; i!=st ; i=D[i]){

 94             Remove(i);

 95             for(int j=R[i] ; j!=i ; j=R[j]) Remove(j);

 96             Dance(d+1);

 97             for(int j=L[i] ; j!=i ; j=L[j]) Resume(j);

 98             Resume(i);

 99         }

100         return;

101     }

102 }dlx;

103 

104 int mat[N][N] , id[N][N];

105 

106 int main()

107 {

108   //  freopen("a.in" , "r" , stdin);

109     while(~scanf("%d%d" , &n , &m))

110     {

111         int size = 0;

112         for(int i=0 ; i<n ; i++)

113             for(int j=0 ; j<m ; j++)

114             {

115                 scanf("%d" , &mat[i][j]);

116                 //这里可以适当加优化,只保留那些有怪兽存在的位置

117                 if(mat[i][j]) size++ , id[i][j] = size;

118             }

119         scanf("%d%d" , &n1 , &m1);

120         int t = (n-n1+1)*(m-m1+1);

121 

122         dlx.init(t , size);

123         for(int k=0 ; k<t ; k++){

124             int row = k/(m-m1+1);

125             int col = k%(m-m1+1);

126             for(int i=row ; i<row+n1 ; i++)

127                 for(int j=col ; j<col+m1 ; j++)

128                     if(mat[i][j]) dlx.link(k+1 , id[i][j]);

129         }

130         dlx.Dance(0);

131         printf("%d\n" , dlx.ans);

132     }

133     return 0;

134 }

 

你可能感兴趣的:(覆盖)