POJ 3740 DLX
来源:互联网 发布:淘宝怎么删除评论 编辑:程序博客网 时间:2024/06/02 07:29
题意:给你一个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///DLXint 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 DLX 精确覆盖模板题
- poj 3740 DLX(精确覆盖)
- POJ 3740 Easy Finding (DLX模板)
- POJ-3740-Easy Finding【DLX精确覆盖】
- POJ 3074 Sudoku DLX
- POJ 3067 Sudoku DLX
- POJ 3076 Sudoku (DLX)
- POJ 3076 sudoku DLX
- poj 2676 Sudoku DLX
- poj - 3740 - Easy Finding(精确覆盖DLX)
- [ACM] POJ 3740 Easy Finding (DLX模板题)
- POJ 3740 Easy Finding(DLX精确覆盖裸题)
- POJ 3076 数独DLX
- POJ 2676 数码问题DLX
- POJ 3074 Sudoku(数据结构,DLX)
- POJ 1084(DLX重复覆盖)
- POJ 3074 Sudoku [DLX] [SDLX]
- Cocos2d-x +Android + Windows 7
- 前端日记 四 ie6下 中文英文数字 对齐
- zedboard--ps工程helloworld的建立(六)
- K60 彩屏ILI9325驱动
- linux中查找文件命令总结
- POJ 3740 DLX
- wince中显示BMP、JPG、Gif以及PNG的方法
- ANDROID ListView 下拉过后自动更新
- 获得嵌套repeater里的控件
- note : Get FilePathName from FILE_OBJECT
- 程序锁的核心原理(获取正在显示的任务栈)
- 如何将JSP跨iframe传递参数
- Nexenta Appliance Tuning
- Linux下通过Pro*C语言访问Oracle(一)