题意:给你一个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. Windows下Redis的安装

    1.安装Redis 官方网站:http://redis.io/ 官方下载:http://redis.io/download 可以根据需要下载不同版本 windows版:https://github.c ...

  2. python解析xml

    python解析xml import xml.dom.minidom as minidom dom = minidom.parse("aa.xml") root = dom.get ...

  3. HTML中发送方式(method)中get和post的比较

    get的方式是将表单控件的控件名name和取值value信息经过编码后,通过URL发送(可以在地址栏里看到).而post则将表单的内容通过http发送.一个 get通过URL传送变量,能传送的数据总量 ...

  4. linux shell if语句

    #!/bin/bash read -p "please input Y/N" keyWord if [ "$keyWord" == "Y" ...

  5. MDX基础

    第一章 看了本书的第一章,总体一个印象,废话真多.话不多说:整理书中知识点,实践出真理! 知识点:MDX语法:简单的函数介绍; 首先语法网上流传的很多,读者应该具备cube(多维数据集)的知识基础,我 ...

  6. View, Activity, Window

    View, Activity, Window 2010-03-02 10:42:56|  分类: android|举报|字号 订阅     对于屏幕显示而言,整个是window,这个window里显示 ...

  7. mysql数据损坏修复方法

    1.myisamchk使用 myisamchk 必须暂时停止 MySQL 服务器.例如,我们要检修 discuz 数据库.执行以下操作:# service mysql stop (停止 MySQL ) ...

  8. hdr_beg(host) 主机名开始

    What does "acl cdn_name hdr_beg(host) -i foor.bar.com" mean in HAProxy's configuration? 在H ...

  9. yum cannot retrieve metalink for repository

    Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again

  10. 浏览器桌面通知(notifications)

    近期在做公司后台管理系统,当有任务到来时,须要通知当事人,可是 当事人有可能在做别的,浏览器有可能会被最小化,这样就非常难看到通知了.经过查找发现有些浏览器能够使用noitfications.能够在桌 ...