[ACM] POJ 3740 Easy Finding (DLX模板题)
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 16178 | Accepted: 4343 |
Description
1.
Input
M, N (M ≤ 16, N ≤ 300). The next M lines every line contains
N integers separated by space.
Output
Sample Input
3 3
0 1 0
0 0 1
1 0 0
4 4
0 0 0 1
1 0 0 0
1 1 0 1
0 1 0 0
Sample Output
Yes, I found it
It is impossible
Source
解题思路:
题意为由01组成的矩阵,问能不能挑出几行使组成的新矩阵每列仅仅有一个1.
套用Dlx模板,只是G++ 超时。C++勉强能过。
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxnode=5000;
const int maxm=310;
const int maxn=18; struct DLX
{
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[maxn];//行头节点
int S[maxm];//每列有多少个节点
int ansd,ans[maxn];//假设有答案,则选了ansd行。详细是哪几行放在ans[ ]数组里面。ans[0~ansd-1]; void init(int _n,int _m)
{
n=_n,m=_m;
for(int i=0;i<=m;i++)
{
S[i]=0;
U[i]=D[i]=i;//初始状态下,上下自己指向自己
L[i]=i-1;
R[i]=i+1;
}
R[m]=0,L[0]=m;
size=m;//编号,每列都有一个头节点,编号1-m
for(int i=1;i<=n;i++)
H[i]=-1;//每一行的头节点
} void link(int r,int c)//第r行,第c列
{
++S[Col[++size]=c];//第size个节点所在的列为c,当前列的节点数++
Row[size]=r;//第size个节点行位置为r
D[size]=D[c];//以下这四句头插法(图是倒着的?)
U[D[c]]=size;
U[size]=c;
D[c]=size;
if(H[r]<0)
H[r]=L[size]=R[size]=size;
else
{
R[size]=R[H[r]];
L[R[H[r]]]=size;
L[size]=H[r];
R[H[r]]=size;
}
} void remove(int c)//删除节点c,以及c上下节点所在的行,每次调用这个函数。都是从列头节点開始向下删除。这里c也能够理解为第c列
{ //由于第c列的列头节点编号为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[Col[j]];
}
} void resume(int c)//恢复节点c,以及c上下节点所在的行(同上,也能够理解为从第c列的头节点開始恢复
{
for(int i=U[c];i!=c;i=U[i])
for(int j=L[i];j!=i;j=L[j])
++S[Col[U[D[j]]=D[U[j]]=j]]; //打这一行太纠结了 T T
L[R[c]]=R[L[c]]=c;
} bool dance(int d)//递归深度
{
if(R[0]==0)
{
ansd=d;
return true;
}
int c=R[0];
for(int i=R[0];i!=0;i=R[i])
if(S[i]<S[c])
c=i;
remove(c);//找到节点数最少的列,当前元素不是原图上0。1的节点,而是列头节点
for(int i=D[c];i!=c;i=D[i])
{
ans[d]=Row[i];//列头节点以下的一个节点
for(int j=R[i];j!=i;j=R[j])
remove(Col[j]);
if(dance(d+1))//找到,返回
return true;
for(int j=L[i];j!=i;j=L[j])
resume(Col[j]);
}
resume(c);
return false;
}
}; DLX x;
int n,m; int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
x.init(n,m);
int num;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>num;
if(num)
x.link(i,j);
}
}
if(!x.dance(0))
printf("It is impossible\n");
else
printf("Yes, I found it\n");
}
return 0;
}
[ACM] POJ 3740 Easy Finding (DLX模板题)的更多相关文章
- [ACM] POJ 3740 Easy Finding (DFS)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16202 Accepted: 4349 Description Give ...
- poj 3740 Easy Finding 二进制压缩枚举dfs 与 DLX模板详细解析
题目链接:http://poj.org/problem?id=3740 题意: 是否从0,1矩阵中选出若干行,使得新的矩阵每一列有且仅有一个1? 原矩阵N*M $ 1<= N <= 16 ...
- poj 3740 Easy Finding(Dancing Links)
Easy Finding Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15668 Accepted: 4163 Des ...
- poj 3740 Easy Finding 精确匹配
题目链接 dlx的第一题, 真是坎坷..... #include <iostream> #include <vector> #include <cstdio> #i ...
- POJ 3740 Easy Finding
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using ...
- POJ 3068 运送危险化学品 最小费用流 模板题
"Shortest" pair of paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1215 ...
- POJ 1287 Networking【kruskal模板题】
传送门:http://poj.org/problem?id=1287 题意:给出n个点 m条边 ,求最小生成树的权 思路:最小生树的模板题,直接跑一遍kruskal即可 代码: #include< ...
- POJ 1502 MPI Maelstrom(模板题——Floyd算法)
题目: BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distri ...
- POJ 1470 Closest Common Ancestors (模板题)(Tarjan离线)【LCA】
<题目链接> 题目大意:给你一棵树,然后进行q次询问,然后要你统计这q次询问中指定的两个节点最近公共祖先出现的次数. 解题分析:LCA模板题,下面用的是离线Tarjan来解决.并且为了代码 ...
随机推荐
- python正则表达式-re模块
目录: 一.正则函数 二.re模块调用 三.贪婪模式 四.分组 五.正则表达式修饰符 六.正则表达式模式 七.常见的正则表达式 导读: 想要使用python的正则表达式功能就需要调用re模块,re模块 ...
- ES6里关于字符串的拓展
一.子串识别 自从 JS 引入了 indexOf() 方法,开发者们就使用它来识别字符串是否存在于其它字符串中.ES6 包含了以下三个方法来满足这类需求: 1.includes():该方法在给定文本存 ...
- ElasticSearch _xpack用户管理
权限管理可以通过kibana的Management界面进行,本篇主要介绍的是通过命令进行权限管理,用户API使您能够从本机域创建,读取,更新和删除用户. 这些用户通常被称为本地用户. 要使用此API, ...
- PL/SQL Developer 显示中文乱码问题解决
PL/SQL Developer 显示中文乱码问题简单版本:首先,通过 select userenv('language') from dual;查询oracle服务器端的编码, 如为: AMERIC ...
- Linux取消挂载,删除用户及其目录
取消挂载 取消挂载命令: umount /dev/sdb 命令umount 文件系统/挂载点 umount /dev/sdb 例如:umount /dev/sdb即可将sdb1取消挂载. 如果出现de ...
- 批量删除Redis中的key
bin/redis-cli -h 192.168.46.151 -p 6379 keys "rulelist*" | xargs bin/redis-cli -h 192.168 ...
- 13 Basic Cat Command Examples in Linux
FROM: http://www.tecmint.com/13-basic-cat-command-examples-in-linux/ The cat (short for “concatenate ...
- 2017.7.21 linux下进程管理工具supervisord的安装与使用
参考来自:http://blog.haohtml.com/archives/15145 0 操作环境 1 supervisord的介绍 Supervisord是用Python实现的一款非常实用的进程管 ...
- 转: Eclispe的远程开发
from: http://www.thinksaas.cn/topics/0/528/528009.html 新项目中用到了所谓的Eclipse远程开发.参考: http://www.eclipse. ...
- 倍福TwinCAT(贝福Beckhoff)基础教程6.1 TwinCAT如何与高级语言通讯
因为使用TwinCAT的人用途不同,重视点就不同.如果用来代替传统PLC+HMI做项目的,很少会需要用到跟高级语言通讯,但是如果是用来做运动控制平台如做机器人运动控制器的,就肯定会用到.不管是否用得上 ...