首页 > 代码库 > ZOJ 3209

ZOJ 3209

精确覆盖

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int maxn=920;const int maxnode=920*550;const int maxr=550;int ans;struct DLX{  int n , sz;                                                 // 行数,节点总数  int S[maxn];                                                // 各列节点总数  int row[maxnode],col[maxnode];                              // 各节点行列编号  int L[maxnode],R[maxnode],U[maxnode],D[maxnode];            // 十字链表   int ansd;                                         // 解   void init(int n )  {    this->n = n ;    for(int i = 0 ; i <= n; i++ )    {      U[i] = i ;      D[i] = i ;      L[i] = i - 1;      R[i] = i + 1;    }    R[n] = 0 ;    L[0] = n;    sz = n + 1 ;    memset(S,0,sizeof(S));  }  void addRow(int r,vector<int> c1)  {    int first = sz;    for(int i = 0 ; i < c1.size(); i++ ){      int c = c1[i];      L[sz] = sz - 1 ; R[sz] = sz + 1 ; D[sz] = c ; U[sz] = U[c];      D[U[c]] = sz; U[c] = sz;      row[sz] = r; col[sz] = c;      S[c] ++ ; sz ++ ;    }    R[sz - 1] = first ; L[first] = sz - 1;  }  // 顺着链表A,遍历除s外的其他元素  #define FOR(i,A,s) for(int i = A[s]; i != s ; i = A[i])   void remove(int c){    L[R[c]] = L[c];    R[L[c]] = R[c];    FOR(i,D,c)      FOR(j,R,i) {U[D[j]] = U[j];D[U[j]] = D[j];--S[col[j]];}  }  void restore(int c){    FOR(i,U,c)      FOR(j,L,i) {++S[col[j]];U[D[j]] = j;D[U[j]] = j; }    L[R[c]] = c;    R[L[c]] = c;  }  void dfs(int d){  	if(d>=ans) return ;    if(R[0] == 0 ){      ansd = d;      ans=min(ans,ansd);    }    // 找S最小的列c    int c = R[0] ;    FOR(i,R,0) if(S[i] < S[c]) c = i;     remove(c);    FOR(i,D,c){      FOR(j,R,i) remove(col[j]);      dfs(d + 1);      FOR(j,L,i) restore(col[j]);    }    restore(c);  }  bool solve(){    dfs(0);  }};DLX solver;int main(){	int T; int n,m ,p; int xx1,xx2,yy1,yy2;	vector<int>colmuns;	scanf("%d",&T);	while(T--){		ans=(1<<30);		scanf("%d%d%d",&n,&m,&p);		solver.init(n*m);		for(int k=1;k<=p;k++){			colmuns.clear();			scanf("%d%d%d%d",&xx1,&yy1,&xx2,&yy2);			for(int i=xx1+1;i<=xx2;i++){				for(int j=yy1+1;j<=yy2;j++){					colmuns.push_back((i-1)*m+j);				}			}			solver.addRow(k,colmuns);		}		solver.solve();		if(ans==(1<<30)) printf("-1\n");		else printf("%d\n",ans);	}	return 0;} 

  

ZOJ 3209