题意:给你一个01矩阵,然后求是否存在选择一些行,使得每一列的1的个数都为1。

思路:貌似朴素的DFS也可以,加点剪枝就可以过。这里贴个DLX的模版。

推荐博客:http://www.cppblog.com/notonlysuccess/archive/2009/07/10/89701.html

这里讲的很详细。

#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 0x3fffffff
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; #define N 5555 ///DLX
int L[N] , R[N] , D[N] , U[N] ,S[N] , C[N] ,st[N] ;//S[] 表示这一列的点数。C[] 表示这个点位于那一列。
int n , m , num , head ; void insert(int col , int pos){//在这一列插入序号为pos的点
int now = col ;
while(D[now] != col) now = D[now] ;
D[now] = pos ;
D[pos] = col ;
U[pos] = now ;
U[col] = pos ;
} void init(){
head = 0 ;
R[head] = 1 ;L[head] = m ;
for (int i = 1 ; i <= m ; i ++ ){//每一行的头指针
if(i == 1)L[i] = head ;
else L[i] = i - 1 ;
if(i == m)R[i] = head ;
else R[i] = i + 1 ;
U[i] = i ;
D[i] = i ;
S[i] = 0 ;
C[i] = i ;
}
num = m ;//已经插入m个节点
int k ;
for (int i = 1 ; i <= n ; i ++ ){
mem(st ,0) ;
for (int j = 1 ; j <= m ; j ++ ){
scanf("%d",&k) ;
if(!k)continue ;
num ++ ;
insert(j , num) ;
if(st[0] == 0){//每行的第一个
L[num] = num ; R[num] = num ;
}else{
L[num] = st[st[0]] ;
R[num] = st[1] ;
R[st[st[0]]] = num ;
L[st[1]] = num ;
}
st[++st[0]] = num ;
C[num] = j ;
S[j] ++ ;
}
}
} void remove(const int &c){//删除
L[R[c]] = L[c] ;R[L[c]] = R[c] ;
for (int i = D[c] ; i != c ; i = D[i]){
for (int j = R[i] ; j != i ; j = R[j]){
U[D[j]] = U[j] ;
D[U[j]] = D[j] ;
-- S[C[j]] ;
}
}
} void resume(const int &c){//恢复
for (int i = U[c] ; i != c ; i = U[i]){
for (int j = L[i] ; j != i ; j = L[j]){
++ S[C[j]] ;
U[D[j]] = j ;
D[U[j]] = j ;
}
}
L[R[c]] = c ;
R[L[c]] = c ;
} int dfs(const int &k){
if(R[head] == head)return 1 ;
int MX = inf ,c ;
for (int t = R[head] ; t != head ; t = R[t]){//找出点最少的一列
if(S[t] < MX){
MX = S[t] ;
c = t ;
}
}
remove(c) ;
for (int i = D[c] ; i != c ; i = D[i]){
for (int j = R[i] ; j != i ; j = R[j]){
remove(C[j]) ;
}
if(dfs(k + 1))return 1 ;
for (int j = L[i] ; j != i ; j = L[j]){
resume(C[j]) ;
}
}
resume(c) ;
return 0 ;
}
int main() {
while(cin >> n >> m){
init() ;
if(dfs(0))puts("Yes, I found it") ;
else puts("It is impossible") ;
}
return 0 ;
}

POJ 3740 DLX的更多相关文章

  1. poj 3740 Easy Finding 二进制压缩枚举dfs 与 DLX模板详细解析

    题目链接:http://poj.org/problem?id=3740 题意: 是否从0,1矩阵中选出若干行,使得新的矩阵每一列有且仅有一个1? 原矩阵N*M $ 1<= N <= 16 ...

  2. [ACM] POJ 3740 Easy Finding (DLX模板题)

    Easy Finding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16178   Accepted: 4343 Des ...

  3. Easy Finding POJ - 3740 (DLX)

    显然这是一道dfs简单题 或许匹配也能做 然而用了dancing links 显然这也是一道模板题 好的吧 调了一上午 终于弄好了模板 Easy Finding Time Limit: 1000MS ...

  4. 【POJ 3740】 Easy Finding

    [题目链接] http://poj.org/problem?id=3740 [算法] Dancing Links算法解精确覆盖问题 详见这篇文章 : https://www.cnblogs.com/g ...

  5. POJ 3740

    http://poj.org/problem?id=3740 这是一道搜索+回溯的题目,也是我第一次接触到回溯. 题意就是找一些行,这些行可以使每一列都只存在一个1. 深搜加回溯: memory:11 ...

  6. poj 3740 Easy Finding 精确匹配

    题目链接 dlx的第一题, 真是坎坷..... #include <iostream> #include <vector> #include <cstdio> #i ...

  7. POJ 3740 Dancing Links

    Dancing Links学习:http://www.cnblogs.com/steady/archive/2011/03/15/1984791.html 以及图文学习:http://www.cnbl ...

  8. poj 3740 Easy Finding(Dancing Links)

    Easy Finding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15668   Accepted: 4163 Des ...

  9. [ACM] POJ 3740 Easy Finding (DFS)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16202   Accepted: 4349 Description Give ...

随机推荐

  1. [汇编语言]-debug跟踪执行

    ffff:0-ffff:d内存中数值求和放入dx寄存器中 代码: add.asm assume cs:code code segment mov ax,0ffffH mov ds,ax mov dx, ...

  2. 使用StackTrace堆栈跟踪记录详细日志(可获取行号)

    上一篇我们提到使用.NET自带的TraceSource实现简单的日志,具体请看<轻松背后的N+疲惫——系统日志>,这一篇注意想讲的是日志的详细记录,包含请求开始到结束的过程中调用的方法链以 ...

  3. KNN(k-nearest neighbor的缩写)又叫最近邻算法

    KNN(k-nearest neighbor的缩写)又叫最近邻算法 机器学习笔记--KNN算法1 前言 Hello ,everyone. 我是小花.大四毕业,留在学校有点事情,就在这里和大家吹吹我们的 ...

  4. SQL Server 与内存相关的术语

    术语 1. virtual address space 虚拟地址空间 它是一个应用程序可以访问的最大地址空间.32位机上是4G(2^32).虚拟地址空间中的数据不一定在物理内存里.可能在缓存文件中. ...

  5. MYSQL 加密的 3 类方法

    背景: 若你想要储存一些由可能包含任意字节值的加密函数返回的结果,使用BLOB列而不是 CHAR 或VARCHAR 列,从而避免由于结尾空格的删除而改变一些数据值的潜在问题. 这一句话来自官方文件,记 ...

  6. Nginx 变量漫谈(三)

    也有一些内建变量是支持改写的,其中一个例子是 $args. 这个变量在读取时返回当前请求的 URL 参数串(即请求 URL 中问号后面的部分,如果有的话 ),而在赋值时可以直接修改参数串.我们来看一个 ...

  7. 将一段含有0的字符数组赋给string

    string有个成员函数,assign() 可以这样: string str; str.assign(temp, sizeof(temp));

  8. javascript事件设计模式

    JavaScript事件设计模式 http://plkong.iteye.com/blog/213543 http://www.docin.com/p-696665922.html

  9. IE9 "CSS 因 Mime 类型不匹配而被忽略“问题

    写页面的时候在chrome,fireforks等页面上显示正常,但是换成IE9之后就完全没有样式了.IE真是个奇葩的怪胎.它的报错信息是’CSS 因 Mime 类型不匹配而被忽略‘,也就是说所有的.c ...

  10. Bootstrap 简洁、直观、强悍、移动设备优先的前端开发框架,让web开发更迅速、简单。

    http://v3.bootcss.com/ 从2.x升级到3.0版本 Bootstrap 3并不向后兼容Bootstrap v2.x.下面章节列出的内容可以作为从v2.x升级到v3.0的通用指南.如 ...