zoukankan      html  css  js  c++  java
  • 【DLX算法】hdu3498 whosyourdaddy

    题意:给你一个01矩阵,让你选择尽可能少的行数,使得这些行的并集能够覆盖到所有列。

    DLX算法求解重复覆盖问题模板,使用估价函数进行剪枝。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn=55+5;
    const int maxr=55+5;
    const int maxnode=55*55+5;
    //ÐбàºÅ´Ó1¿ªÊ¼£¬ÁбàºÅΪ1~n£¬½áµã0ÊDZíÍ·½áµã£»½áµã1~nÊǸ÷Áж¥²¿µÄÐéÄâ½áµã 
    struct DLX{
    	int n,sz;//ÁÐÊý£¬½áµã×ÜÊý 
    	int S[maxn];//¸÷ÁнáµãÊý 
    	int row[maxnode],col[maxnode];//¸÷½áµãËùÔÚµÄÐÐÁбàºÅ 
    	int L[maxnode],R[maxnode],U[maxnode],D[maxnode];
    	int ansd,ans[maxr];//½â 
    	void init(int n){//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; ansd=1000000007;
    		memset(S,0,sizeof(S));
    	}
    	void addRow(int r,vector<int> columns){
    		int first=sz;
    		for(int i=0;i<columns.size();++i){
    			int c=columns[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;
    	}
    	bool dfs(int d){
    //		printf("%d",d);
    		if(R[0]==0){//ÕÒµ½½â 
    			ansd=d;//¼Ç¼½âµÄ³¤¶È 
    			return 1;
    		}
    		//ÕÒ½áµãÊý×îСµÄÁÐc 
    		int c=R[0];//µÚÒ»¸öδɾ³ýµÄÁÐ 
    		FOR(i,R,0){
    			if(S[i]<S[c]){
    				c=i;
    			}
    		}
    		remove(c);//ɾ³ýµÚcÁÐ 
    		FOR(i,D,c){//ÓýáµãiËùÔÚÐи²¸ÇµÚcÁÐ 
    			ans[d]=row[i];
    			FOR(j,R,i){
    				remove(col[j]);//ɾ³ý½áµãiËùÔÚÐÐÄܸ²¸ÇµÄËùÓÐÆäËûÁÐ 
    			}
    			if(dfs(d+1)){
    				return 1;
    			}
    			FOR(j,L,i){
    				restore(col[j]);//»Ö¸´½áµãiËùÔÚÐÐÄܸ²¸ÇµÄÆäËûËùÓÐÁÐ 
    			}
    		}
    		restore(c);//»Ö¸´µÚcÁÐ 
    		return 0;
    	}
    	bool solve(vector<int>& v){
    		v.clear();
    		if(!dfs(0)){
    			return 0;
    		}
    		for(int i=0;i<ansd;++i){
    			v.push_back(ans[i]);
    		}
    		return 1;
    	}
    	
    	void remov2(int c){
    		FOR(i,D,c){
    			L[R[i]]=L[i];
    			R[L[i]]=R[i];
    		}
        }
        void restor2(int c){
    		FOR(i,U,c){
    			L[R[i]]=R[L[i]]=i;
    		}
        }
        int f(){//¹À¼Ûº¯Êý 
        	bool vis[maxn];
        	int res=0;
        	FOR(i,R,0){
        		vis[i]=1;
        	}
        	FOR(i,R,0){
        		if(vis[i]){
        			++res;
        			vis[i]=0;
        			FOR(j,D,i){
        				FOR(k,R,j){
        					vis[col[k]]=0;
        				}
        			}
        		}
        	}
        	return res;
        }
        void df2(int d){
        	if(d+f()>=ansd){
        		return;
        	}
    		if(R[0]==0){//ÕÒµ½½â 
    			ansd=min(ansd,d);//¼Ç¼½âµÄ³¤¶È 
    			return;
    		}
    		//ÕÒ½áµãÊý×îСµÄÁÐc 
    		int c=R[0];//µÚÒ»¸öδɾ³ýµÄÁÐ 
    		FOR(i,R,0){
    			if(S[i]<S[c]){
    				c=i;
    			}
    		}
    		FOR(i,D,c){
    			remov2(i);
    			FOR(j,R,i){
    				remov2(j);
    			}
    			df2(d+1);
    			FOR(j,L,i){
    				restor2(j);
    			}
    			restor2(i);
    		}
    	}
        
    }dlx;
    int n,m;
    bool a[60][60];
    int main(){
    	//freopen("hdu3498.in","r",stdin);
    	int x,y;
    	while(scanf("%d%d",&n,&m)!=EOF){
    		dlx.init(n);
    		memset(a,0,sizeof(a));
    		for(int i=1;i<=n;++i){
    			a[i][i]=1;
    		}
    		for(int i=1;i<=m;++i){
    			scanf("%d%d",&x,&y);
    			a[x][y]=a[y][x]=1;
    		}
    		for(int i=1;i<=n;++i){
    			vector<int> columns;
    			for(int j=1;j<=n;++j){
    				if(a[i][j]){
    					columns.push_back(j);
    				}
    			}
    			if(!columns.empty()){
    				dlx.addRow(i,columns);
    			}
    		}
    		dlx.df2(0);
    		printf("%d
    ",dlx.ansd);
    	}
    	return 0;
    }
  • 相关阅读:
    洛谷P1056_排座椅 贪心+桶排思想
    NOIP普及组相关
    洛谷P1464_Function 记忆化搜索
    Xcode的使用技巧
    MAC_XCODE清理
    输入框跟随键盘移动效果的实现
    #pragma的进阶用法
    iOS 逆向
    警告框
    UIImageView设置圆角的方式
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7752557.html
Copyright © 2011-2022 走看看