zoukankan      html  css  js  c++  java
  • luogu P4929 【模板】舞蹈链 DLX

    LINK:舞蹈链

    具体复杂度我也不知道 但是 搜索速度极快.

    原因大概是因为 每次检索的时间少 有一定的剪枝.

    花了2h大概了解了这个东西 吐槽一下题解根本看不懂 只能理解大概的想法 核心的链表不太懂.

    于是直接看代码了 应该算是把代码给理解了 于是就懂了链表是怎么操作的。

    首先 对于列先建立一个循环链表 r[0]==0时 说明所有的列被填完.

    没必要建立0的点 因为没有什么用 只需要知道1在哪即可。

    对于1的结点新建结点 然后这些结点组成一个双向十字链表 注意和上面那个循环链表不连在一起.

    这个循环链表容易建立 值得一提的是需要检索列的链表 所以需要在列的链表头处加一个标号 使得能够找到.

    而横排则不需要 直接利用列就可以找到.

    下面是删除.

    找到一列之后 随便找一行 删除当前行 同时意味着 当前行上所有1的位置所在列被删掉.

    考虑删掉列的操作 这些列所在的行要被删掉 所以再枚举行 删掉列.

    回溯的时候 也很容易还原.

    这样进行搜索即可.

    理解海星 下次再加深理解好了.

    const int MAXN=5510;
    int n,m,cnt,ans;
    int ans1[MAXN];
    int l[MAXN],r[MAXN],col[MAXN],row[MAXN],u[MAXN],d[MAXN],h[MAXN],s[MAXN];
    inline void prepare()
    {
    	rep(0,m,i)
    	{
    		r[i]=i+1;
    		l[i]=i-1;
    		u[i]=d[i]=i;
    	}
    	r[m]=0;l[0]=m;
    	memset(h,-1,sizeof(h));
    	memset(s,0,sizeof(s));
    	cnt=m+1;
    }
    inline void Link(int x,int y)
    {
    	++s[y];//某一列的结点个数.
    	
    	row[cnt]=x;col[cnt]=y;
    	
    	u[cnt]=y;d[cnt]=d[y];//显然这个地方是纵向循环链表.
    	u[d[y]]=cnt;d[y]=cnt;
    	
    	if(h[x]==-1)h[x]=r[cnt]=l[cnt]=cnt;
    	else
    	{
    		r[cnt]=h[x];//显然这个地方是横向循环链表.
    		l[cnt]=l[h[x]];//容易得到h[x]表示当前行的首结点 同时也是末结点.
    		r[l[h[x]]]=cnt;
    		l[h[x]]=cnt;
    	}
    	++cnt;
    }
    inline void remove(int y)
    {
    	r[l[y]]=r[y];l[r[y]]=l[y];
    	for(int i=d[y];i!=y;i=d[i])
    	{
    		for(int j=r[i];j!=i;j=r[j])
    		{
    			u[d[j]]=u[j];
    			d[u[j]]=d[j];
    			--s[col[j]];
    		}
    	}
    }
    inline void resume(int y)
    {
    	for(int i=u[y];i!=y;i=u[i])
    	{
    		for(int j=l[i];j!=i;j=l[j])
    		{
    			u[d[j]]=j;
    			d[u[j]]=j;
    			++s[col[j]];
    		}
    	}
    	r[l[y]]=y;l[r[y]]=y;
    }
    inline void dance(int dep)
    {
    	if(r[0]==0)
    	{
    		rep(1,dep-1,i)put_(ans1[i]);
    		exit(0);
    	}
    	int y=r[0];
    	for(int i=r[0];i;i=r[i])if(s[i]<s[y])y=i;
    	remove(y);
    	for(int i=d[y];i!=y;i=d[i])
    	{
    		ans1[dep]=row[i];
    		for(int j=r[i];j!=i;j=r[j])remove(col[j]);
    		dance(dep+1);
    		for(int j=l[i];j!=i;j=l[j])resume(col[j]);
    	}
    	resume(y);
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(m);prepare();
    	rep(1,n,i)
    	{
    		rep(1,m,j)
    		{
    			int get(op);
    			if(op)Link(i,j);
    		}
    	}
    	dance(1);puts("No Solution!");
    	return 0;
    }
    
  • 相关阅读:
    IIS代理
    NODEJS
    js图表插件
    注册nodejs程序为windows服务
    中断子系统7_中断出口处理
    Leetcode: Sort List
    jquery 鼠标经过放大图片
    在Tomcat上运行ADF Essentials应用
    简谈HTML5与APP技术应用
    Boost的Serialization和SmartPoint搭配使用
  • 原文地址:https://www.cnblogs.com/chdy/p/12891791.html
Copyright © 2011-2022 走看看