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 ...
随机推荐
- Font Awesome 4.0.3 字体图标完美兼容IE7
1.下载Font Awesome 4.0.3兼容包,http://www.thinkcmf.com/index.php?m=font 2.解压,并放到自己网站系统合适的位置(如果你的站已使用Font ...
- newifi升级固件及开启SSH
1.固件去官方社区下载 2.开启SSH 连接newifi访问http://192.168.99.1/newifi/ifiwen_hss.html 看到返回success 说明开启SSH 3.使用 ...
- Square Coins(母函数)
Square Coins 点我 Problem Description People in Silverland use square coins. Not only they have square ...
- 通过HOOK控制进程的创建
一. 简介 最近,我了解到一个叫做Sanctuary的相当有趣的安全产品.它能够阻止任何程序的运行-这些程序没有显示在软件列表中-该表中的程序被允许在一个特定的机器上运行.结果,PC用户得到保护而免于 ...
- SQL表名,应该用复数还是单数
用单数形式更佳,理由如下: 1.概念直观. 你有一个袋子,里面有好多个苹果,你会说这是个苹果袋.但无论里面有0,1,百万个苹果,它依然是个袋子.表也是如此,表明需要描述清楚,表里面包含的对象,而非有多 ...
- iOS GCD详解
前言 对初学者来说,GCD似乎是一道迈不过去的坎,很多人在同步.异步.串行.并行和死锁这几个名词的漩涡中渐渐放弃治疗.本文将使用图文表并茂的方式给大家形象地解释其中的原理和规律. 线程.任务和队列的概 ...
- Android面试题目及其答案
转自:http://blog.csdn.net/wwj_748/article/details/8868640 Android面试题目及其答案 1.Android dvm的进程和Linux的进程, 应 ...
- KMP快速模式匹配的java实现
假期实在无聊赖啊.把这个算法实现了一下即算是打发时间也算练练手了. KMP算法的关键是用归纳法计算失败函数.网上很详细了.下面直接给出代码. /** * * @author Vincent * */ ...
- poj 2186 (强连通缩点)
题意:有N只奶牛,奶牛有自己认为最受欢迎的奶牛.奶牛们的这种“认为”是单向可传递的,当A认为B最受欢迎(B不一定认为A最受欢迎),且B认为C最受欢迎时,A一定也认为C最受欢迎.现在给出M对这样的“认为 ...
- Linux之旅(1): diff, patch和quilt (下)
Linux之旅(1): diff, patch和quilt (下) 2 quilt 我们自己的项目能够用cvs或svn管理所有代码.但有时我们要使用其它开发人员维护的项目.我们须要改动一些文件,但又不 ...