HUST 1017 Exact cover(舞蹈链不能为了ac而ac)

2024-04-20 12:08

本文主要是介绍HUST 1017 Exact cover(舞蹈链不能为了ac而ac),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接:[kuangbin带你飞]专题三 Dancing Links A - Exact cover

题意

给定一01矩阵,问是否能够精确覆盖(就是选取任意行,这些行的1所在的列互不冲突且完整覆盖所有列),若有输出行号(要按递增顺序输出),否则输出NO。

思路

ps:两个礼拜前大略看了下舞蹈链(虽然英文名听起来更高端,但还是更喜欢它的中文名字),很精妙但也让人一看就惰性必生不愿再看,今天耐心再仔细理解了下,总算是a的刷题生涯第一道精确覆盖题(人有时候还是要逼自己一把,战胜惰性才能进步)。

没什么思路,标准的舞蹈链模版题,理解了舞蹈链就能a了。
学习舞蹈链,推荐此博文,相当清晰:跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
代码上有详细的注释,但有一处有必要分享一下。

for(int i=R[0]; i!=0; i=R[i])if(S[i] < S[col])col = i;

上面这段代码作用是每次选取元素最少的列进行操作,可以有效减少递归层数,从而加快程序效率。
因为本人好奇,取消了它试了一下,发现wrong(按理也应该是timelimit啊),一试再试,发现是得出的行号没有排序的原因,加上对结果的排序就好了。
但本人又好奇了,一再思索,终究还是想不出来上述代码为什么能够使结果递增序,于是做了一组数据:
5 5
2 4 5
3 1 3 4
1 5
1 2
2 1 5
测试后发现无论加不加上述代码结果都不是递增序的,也就是说上述代码只是加速的功能而已。
也就是说,测试数据太水,所有没加排序的代码都应该被wrong。(很好奇那么多题解为什么没有一个带排序的,希望自己不要成为为了ac而ac的人)。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>using namespace std;const int N = 1009;
const int MAX = 1000009;int U[MAX], D[MAX], L[MAX], R[MAX];//数组模拟链表指向(上下左右)
int C[MAX], M[MAX];//节点所在列与行
int S[N];//储存每列的元素数量
int H[N];//行头指针
int ANS[N];//结果保存数组void link(int row, int col, int id)//将节点加入链表
{C[id] = col; M[id] = row;//记录行列U[id] = U[col]; D[U[col]] = id;//上下连接D[id] = col; U[col] = id;if(H[row] == -1)//左右连接(使用表头方便头插)H[row] = L[id] = R[id] = id;else{L[id] = L[H[row]]; R[L[H[row]]] = id;L[H[row]] = id; R[id] = H[row];}S[col]++;
}void remove(int col)//删除列
{R[L[col]] = R[col];L[R[col]] = L[col];for(int i=D[col]; i!=col; 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(int col)//恢复列(先删的后恢复,后删的先恢复,所以跟remove反向操作)
{R[L[col]] = col;L[R[col]] = col;for(int i=U[col]; i!=col; i=U[i]){for(int j=L[i]; j!=i; j=L[j]){U[D[j]] = j;D[U[j]] = j;S[C[j]]++;}}
}bool dance(int k)
{if(!R[0])//列辅助数组为空表示已得解{printf("%d", k);sort(ANS, ANS+k);//对结果排序。for(int i=0; i<k; i++)printf(" %d", ANS[i]);printf("\n");return true;}int col = R[0];for(int i=R[0]; i!=0; i=R[i])//加速,上文已说明if(S[i] < S[col])col = i;remove(col);//删除列for(int i=D[col]; i!=col; i=D[i])//尝试该列每行一次做为解{ANS[k] = M[i];// 记录行号for(int j=R[i]; j!=i; j=R[j])//删除该行元素说相关的列remove(C[j]);if(dance(k+1))return true;for(int j=L[i]; j!=i; j=L[j])//恢复resume(C[j]);}resume(col);//恢复列return false;
}int main()
{int n, m;while(~scanf("%d%d", &n, &m)){for(int i=0; i<=m; i++)//初始化{L[i+1] = i;R[i] = i+1;U[i] = D[i] = i;S[i] = 0;}L[0] = m;R[m] = 0;int id = m+1;for(int i=1; i<=n; i++){int num;scanf("%d", &num);H[i] = -1;while(num--){int col;scanf("%d", &col);link(i, col, id++);}}if(!dance(0))printf("NO\n");}return 0;
}

这篇关于HUST 1017 Exact cover(舞蹈链不能为了ac而ac)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/920217

相关文章

python 在pycharm下能导入外面的模块,到terminal下就不能导入

项目结构如下,在ic2ctw.py 中导入util,在pycharm下不报错,但是到terminal下运行报错  File "deal_data/ic2ctw.py", line 3, in <module>     import util 解决方案: 暂时方案:在终端下:export PYTHONPATH=/Users/fujingling/PycharmProjects/PSENe

Leetcode 3195. Find the Minimum Area to Cover All Ones I

Leetcode 3195. Find the Minimum Area to Cover All Ones I 1. 解题思路2. 代码实现 题目链接:3195. Find the Minimum Area to Cover All Ones I 1. 解题思路 这一题还是挺简单的,只要找到所有1所在的元素的上下左右4个边界,作为目标矩形的四个边即可。 2. 代码实现 给出python

java编程:命令行输入的三个整数判断是否构成三角形,不能就抛异常。

写一个方法void sanjiao(int a,int b,int c),判断三个参数是否能构成一个三角形,如果不能则抛出 异常IllegalArgumentException,显示异常信息“a,b,c不能构成三角形”, 如果可以构成则显示三角形三个边长,在主方法中得到命令行输入的三个整数,调用此方法,并捕获异常。 附源代码: package 异常;public class Sa

虚拟机不能联网的问题

如果虚拟机在NAT模式下不能联网的话,有可能是你的计算机服务里面的VMwareNAT service,VMware DHCP Service没启动。

https://curl.trillworks.com不能用的解决方法

gitee源码:https://gitee.com/Project0ne/curlconverter 首先打开上面的链接 然后下载文件 下载文件到本地 然后安装node.js(Node.js official website.)不会的自行百度,这里不做过多赘述。 在curlconverter文件夹下面打开终端(在文件夹下面右键-在终端打开) 输入 npm init -y 然后安装curl

【Java】Hashmap不能用基本的数据类型 Dimensions expected after this token

http://moto0421.iteye.com/blog/1143777 今天试了一下HahsMap, 采用如下形似定义 (这个下面是用了csdn的一位同仁的文章,仅作为讲解参考,请见谅) HashMap<int,String> map=new HashMap<int,String>();  map.put(1,"a");  map.put(2,"b");  map.pu

技术师增强版,系统级别的工具!【不能用】

数据安全是每位计算机用户都关心的重要问题。在日常使用中,我们经常面临文件丢失、系统崩溃或病毒感染等风险。为了解决这些问题,我们需要可靠且高效的数据备份与恢复工具。本文将介绍一款优秀的备份软件:傲梅轻松备份技术师增强版,它可以为Windows操作系统用户提供了全面的数据保护解决方案。 傲梅轻松备份技术师增强版是由傲梅官方推出的一款专业备份工具。它以业界领先的备份速度和用户友好的操作界面著称,为

Android不能调用java.awt的原因及解决办法和思考

android 里面不能使用awt,底层没有具体的实现awt android里面的窗口创建过程决定了界面只能是android里面的组建。 android的组件都是通过远程的IPC调用完成的,也就是说服务端有什么功能才能用什么功能。 不是所有用java写的程序都能在标准jvm中运行的。 android中的虚拟机是修改过的,跟标准的JVM不同,比如对一张图片的解析,android

程序员为什么不能一次性写好,需要一直改Bug?

程序员在编写代码时不能一次性写好,而是需要不断修改Bug,这主要是由几个因素导致的: 复杂性:软件开发是一个高度复杂的过程,涉及到多个模块、功能、逻辑和数据的交互。即使是最有经验的程序员,也很难一次性预见并处理所有可能出现的问题。需求变更:在软件开发过程中,客户需求经常会发生变化。这些变更可能导致已经编写好的代码需要调整,从而引入新的Bug。技术更新:随着技术的不断发展,新的编程语言、框架和库不