POJ 3740 DLX
题意:给你一个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的更多相关文章
- poj 3740 Easy Finding 二进制压缩枚举dfs 与 DLX模板详细解析
题目链接:http://poj.org/problem?id=3740 题意: 是否从0,1矩阵中选出若干行,使得新的矩阵每一列有且仅有一个1? 原矩阵N*M $ 1<= N <= 16 ...
- [ACM] POJ 3740 Easy Finding (DLX模板题)
Easy Finding Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16178 Accepted: 4343 Des ...
- Easy Finding POJ - 3740 (DLX)
显然这是一道dfs简单题 或许匹配也能做 然而用了dancing links 显然这也是一道模板题 好的吧 调了一上午 终于弄好了模板 Easy Finding Time Limit: 1000MS ...
- 【POJ 3740】 Easy Finding
[题目链接] http://poj.org/problem?id=3740 [算法] Dancing Links算法解精确覆盖问题 详见这篇文章 : https://www.cnblogs.com/g ...
- POJ 3740
http://poj.org/problem?id=3740 这是一道搜索+回溯的题目,也是我第一次接触到回溯. 题意就是找一些行,这些行可以使每一列都只存在一个1. 深搜加回溯: memory:11 ...
- poj 3740 Easy Finding 精确匹配
题目链接 dlx的第一题, 真是坎坷..... #include <iostream> #include <vector> #include <cstdio> #i ...
- POJ 3740 Dancing Links
Dancing Links学习:http://www.cnblogs.com/steady/archive/2011/03/15/1984791.html 以及图文学习:http://www.cnbl ...
- poj 3740 Easy Finding(Dancing Links)
Easy Finding Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15668 Accepted: 4163 Des ...
- [ACM] POJ 3740 Easy Finding (DFS)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16202 Accepted: 4349 Description Give ...
随机推荐
- FTP下文件夹权限的设置755,766,777,644代表什么意思
一般情况下,为了网站更安全,我们需要给文件或文件夹设置权限,在采用FTP登录的方式下,经常会用到755,766,777,644等设置. 具体这些数字都代表什么意思呢? 这三个数字分别表示:不同用户或用 ...
- IBM Minus One(water)
IBM Minus One Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- Oracle EBS-SQL (PO-12):检查期间请购单的下达记录数.sql
SELECT DECODE(PRHA.INTERFACE_SOURCE_CODE,'','手工','MRP','自动') 下达方式, PRHA.CREATION_DATE ...
- Java魔法堂:打包知识点之META-INF/MAINFEST.MF(转)
一.前言 通过执行形如 jar -cvf src.jar src 命令将多个.class文件打包成JAR包时,你会发现JAR包中除了src目录外还多了个MATE-INF/MAINFEST.MF,那是为 ...
- Linux命令行之逗趣无极限
Linux命令行之逗趣无极限 . Linux"sl"命令行 尽管"sl"代表了"蒸汽机机头",但它是用来提醒那些命令行控们别把"l ...
- zlog
zlog源码包下载地址https://github.com/HardySimpson/zlog zlog使用手册http://blog.csdn.net/yangzhenzhen/article/de ...
- Java程序员应该知道的10个面向对象理论
英文原文:10-object-oriented-design-principles 面向对象理论是面向对象编程的核心,但是我发现大部分 Java 程序员热衷于像单例模式.装饰者模式或观察者模式这样的设 ...
- linux下的时间及时区设置
一.时间设置及同步 1修改系统时间 #date -s 06/18/14 #date -s 14:20:50 2命令查看.设置硬件时间 #hwclock --show 或者clock --show ...
- Android学习自定义Dialog
Dialog是Android提供的各种对话框的基类,和上篇的DialogFragment类似.为什么还要介绍Dialog呢,因为DialogFragment只能运行在Android3.0以上的系统中. ...
- (七)Android中AIDL的应用与理解
一.跨应用启动Service Intent serviceIntent=new Intent();serviceIntent.setComponent(new ComponentName(" ...