题意:多组数据,每组数据给你几行数,要求选出当中几行。使得每一列都有且仅有一个1。询问是可不可行,或者说能不能找出来。

题解:1、暴搜。2、DLX(Dancing links)。

本文写的是DLX。

算法參考白书P406或者http://www.cnblogs.com/grenet/p/3145800.html

我说一些仔细的东西,就是删除操作的形状是

|

——|————

——|————

——|————

被删除的点们之间的联系不用删,能够保留。准确地说它并非删去了这些点,而是删去这个形。

并且恢复时要反着恢复。

首先先确定从哪一列删除,进行一次remove,然后枚举这一列的每一行。对其进行remove。然后dfs,然后再resume。

跳出循环时再resume确定列。

附代码,应该非常好看,仅仅要略耐心 一点点点点点。。

我保证绝对照网上其它人的可读性强。

哦,对了。并不须要写点、行、列的单独的remove和resume函数。那太傻了,写模板也不须要,我想这应该永远用不上的。。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 400
#define NN 10000
using namespace std;
struct DLX
{
int U[NN],D[NN],L[NN],R[NN],C[NN];
int H[NN],T[NN],cnt;
inline void init(int m)
{
cnt=0;
memset(H,0,sizeof(H));
for(cnt=0;cnt<=m;cnt++)
{
U[cnt]=D[cnt]=C[cnt]=cnt;
L[cnt]=cnt-1,R[cnt]=cnt+1;
}
L[0]=--cnt,R[cnt]=0;
}
inline void newnode(int x,int y)
{
C[++cnt]=y;T[y]++; if(!H[x])H[x]=L[cnt]=R[cnt]=cnt;
else L[cnt]=H[x],R[cnt]=R[H[x]];
R[H[x]]=L[R[H[x]]]=cnt,H[x]=cnt; U[cnt]=U[y],D[cnt]=y;
U[y]=D[U[y]]=cnt;
}
inline void scan(int n,int m)
{
int i,j,k;
for(i=1;i<=n;i++)for(j=1;j<=m;j++)
{
scanf("%d",&k);
if(k)newnode(i,j);
}
}
inline void remove(int x)
{
for(int i=D[x];i!=x;i=D[i])
{
for(int j=R[i];j!=i;j=R[j])
{
U[D[j]]=U[j];
D[U[j]]=D[j];
T[C[j]]--;
}
}
L[R[x]]=L[x];
R[L[x]]=R[x];
}
inline void resume(int x)
{
for(int i=U[x];i!=x;i=U[i])
{
for(int j=L[i];j!=i;j=L[j])
{
U[D[j]]=j;
D[U[j]]=j;
T[C[j]]++;
}
}
L[R[x]]=x;
R[L[x]]=x;
}
inline bool dfs()
{
if(!R[0])return true;
int S=R[0],W=T[S],i,j;
for(i=R[S];i;i=R[i])if(T[i]<W)
{
W=T[i];
S=i;
}
remove(S);
for(i=D[S];i!=S;i=D[i])
{
for(j=R[i];j!=i;j=R[j])remove(C[j]);
if(dfs())return true;
for(j=L[i];j!=i;j=L[j])resume(C[j]);
}
resume(S);
return false;
}
}dlx;
int main()
{
// freopen("test.in","r",stdin);
// freopen("my.out","w",stdout);
int n,m;
while(~scanf("%d%d",&n,&m))
{
dlx.init(m);
dlx.scan(n,m);
if(dlx.dfs())puts("Yes, I found it");
else puts("It is impossible");
}
return 0;
}

给点福利。

专属那些输出调试者。

	inline void print_line(int x)
{
int i=x;
do{
printf("%d->",i);
i=R[i];
}while(i!=x);
puts("");
}
inline void print_list(int x)
{
int i=x;
do{
printf("%d->",i);
i=D[i];
}while(i!=x);
puts("");
}
inline void print(int x)
{
int i=x;
do{
print_list(i);
puts("|");
i=R[i];
}while(i!=x);
puts("");
puts("");
}

当然。你非得点行列写单独操作我也不拦你。

        inline void remove_point(int x)
{
D[U[x]]=D[x];
U[D[x]]=U[x];
R[L[x]]=R[x];
L[R[x]]=L[x];
}
inline void resume_point(int x)
{
D[U[x]]=x;
U[D[x]]=x;
R[L[x]]=x;
L[R[x]]=x;
}
inline void remove_line(int x)
{
int i=x;
do{
U[D[i]]=U[i];
D[U[i]]=D[i];
i=R[i];
}while(i!=x);
}
inline void resume_line(int x)
{
int i=x;
do{
U[D[i]]=i;
D[U[i]]=i;
i=L[i];
}while(i!=x);
}
inline void remove_list(int x)
{
int i=x;
do{
R[L[i]]=R[i];
L[R[i]]=L[i];
i=D[i];
}while(i!=x);
}
inline void resume_list(int x)
{
int i=x;
do{
R[L[i]]=i;
L[R[i]]=i;
i=U[i];
}while(i!=x);
}

然后数据我就不贴了,直接去看3740discuss吧,有两组。

【POJ3740】Easy Finding DLX(Dancing Links)精确覆盖问题的更多相关文章

  1. HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )

    推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...

  2. 【转】Dancing Links精确覆盖问题

    原文链接:http://sqybi.com/works/dlxcn/ (只转载过来一部分,全文请看原文,感觉讲得很好~)正文    精确覆盖问题    解决精确覆盖问题    舞蹈步骤    效率分析 ...

  3. hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)

    hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...

  4. hust 1017 dancing links 精确覆盖模板题

    最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...

  5. ZOJ 3209 Treasure Map (Dancing Links 精确覆盖 )

    题意 :  给你一个大小为 n * m 的矩形 , 坐标是( 0 , 0 ) ~ ( n , m )  .然后给你 p 个小矩形 . 坐标是( x1 , y1 ) ~ ( x2 , y2 ) , 你选 ...

  6. POJ3074 Sudoku —— Dancing Links 精确覆盖

    题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissio ...

  7. HUST1017 Exact cover —— Dancing Links 精确覆盖 模板题

    题目链接:https://vjudge.net/problem/HUST-1017 1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 7673 次提交 3898 次 ...

  8. HDU5046 Airport dancing links 重复覆盖+二分

    这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...

  9. dancing link 精确覆盖 重复覆盖 (DLX)

    申明:因为转载的没有给出转载链接,我就把他的链接附上,请尊重原创: http://www.cnblogs.com/-sunshine/p/3358922.html 如果谁知道原创链接 给一下,请尊重原 ...

随机推荐

  1. BZOJ 4815 [Cqoi2017]小Q的表格 ——欧拉函数

    把式子化简一波. 发现一个比较厉害的性质:每个点只能影响到行列下标$gcd$与它相同的点. 然后就可以计算$\sum_{g<=k}f(g,g)*\sum_{i<=k}\sum_{j< ...

  2. BZOJ 2298: [HAOI2011]problem a【动态规划】

    Description 一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低.”问最少有几个人没有说真话(可能有相同的分数) Input 第一行一个整数n,接下来n行每行两个 ...

  3. 使用HttpClient实现对第三方服务器的请求并接受返回数据

    /* * 创建日期 2017-4-7 * * TODO 要更改此生成的文件的模板,请转至 * 窗口 - 首选项 - Java - 代码样式 - 代码模板 */ package com.enfo.int ...

  4. 标准C程序设计七---30

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  5. Hibrenate load 和 get

    这次我们来谈一下Hibernate3.2 Session加载数据时get和load方法的区别(Hibernate 3以后的版本就用get()方法取代find()这个方法了),其实这个在网上有很多的论述 ...

  6. sulime text 常用快捷键总结

    Sublime Text 3汉化中文版主要特色: -语法高亮.代码提示补全.代码折叠.自定义皮肤/配色方案.多便签 -代码地图.多种界面布局与全屏免打扰模式 -完全开放的用户自定义配置与神奇实用的编辑 ...

  7. T1245 最小的N个和 codevs

    http://codevs.cn/problem/1245/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 有两个长度 ...

  8. Ubuntu 16.04通过Snap安装应用程序

    16.04LTS可以说是一个不寻常的5年支持版本,同时也带来了Snap应用,并通过Snap可以安装众多的软件包.需要注意的是,Snap是一个全新的软件包架构,但是同样也比其它的软件包大很多. 简单的安 ...

  9. 微软CIO如何与业务部门打交道?

    微软公司副总裁兼CIO Tony Scott是一个非常智慧的人,他拒绝和CEO讨论IT成本的问题,认为IT不应该谈论成本,而是应该谈论IT提供服务的价值.在满足业务部门需求.为业务部门提供适当的IT支 ...

  10. 使用MVP模式重构代码

    之前写了两篇关于MVP模式的文章,主要讲得都是一些概念,这里谈谈自己在Android项目中使用MVP模式的真实感受,并以实例的形式一起尝试来使用MVP模式去重构我们现有的代码. 有兴趣的童鞋可以先去阅 ...