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
" , dlx.ans);
132     }
133     return 0;
134 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4508962.html