HUST 1017 Exact cover DLX

本文介绍了一个利用 Dancing Links 算法解决精确覆盖问题的经典案例。通过构建矩阵并采用高效的回溯搜索算法,实现了从输入矩阵中找出能使每列恰好有一个1的行集合的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:一个n×m行的矩阵,每个格子可能是 0 或者1  现在让你选择 几行  使得 每一列 有且只有一个1.(精确覆盖模板题)

解题思路:

dancing links 模板 

关于dancing links  献上几篇必看论文 :http://par.buaa.edu.cn/acm-icpc/filepool/r/35/

板子用的kuangbin的板子(还是适牛的。。)

解题思路:

  1 // File Name: hust1017.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年10月04日 星期六 16时47分57秒
  4 
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #define LL long long
 25 const int maxnode = 100010;
 26 const int MaxM = 1010;
 27 const int MaxN = 1010;
 28 using namespace std;
 29 struct DLX
 30 {
 31     int n ,m ,size;
 32     int L[maxnode],R[maxnode],U[maxnode],D[maxnode],Row[maxnode],Col[maxnode];
 33     int ansd,ans[MaxN];
 34     int H[MaxN],S[MaxM];
 35     void init(int _n,int _m)
 36     {
 37         n = _n;
 38         m = _m;
 39         for(int i = 0;i <= m;i++)
 40         {
 41             S[i] = 0; // S 代表的是每一列的颜色
 42             U[i] = D[i] = i;
 43             L[i] = i-1;
 44             R[i] = i+1;
 45         }
 46         R[m] = 0; L[0] = m;
 47         size = m;
 48         for(int i = 1;i <= n;i++)
 49             H[i] = -1;  //  H[i]  代表第I 行的头
 50     }
 51     void Link(int r,int c)
 52     {
 53         ++S[Col[++size]=c];
 54         Row[size] = r;
 55         D[size] = D[c];
 56         U[D[c]] = size;
 57         U[size] = c;
 58         D[c] = size;
 59         if(H[r] < 0)H[r] = L[size] = R[size] = size;
 60         else
 61         {
 62             R[size] = R[H[r]];
 63             L[R[H[r]]] = size;
 64             L[size] = H[r];
 65             R[H[r]] = size; // 插入到  H[r] 的右边
 66         }
 67     }
 68     void remove(int c) //列为单位,横向
 69     {
 70         L[R[c]] = L[c]; R[L[c]] = R[c];
 71         for(int i = D[c];i != c;i = D[i])
 72             for(int j = R[i];j != i;j = R[j])
 73             {
 74                 U[D[j]] = U[j];
 75                 D[U[j]] = D[j];
 76                 --S[Col[j]];
 77             }//删除一列,k行
 78     }
 79     void resume(int c)
 80     {
 81         L[R[c]] = R[L[c]] = c;
 82         for(int i = U[c];i != c; i = U[i])
 83             for(int j = L[i];j != i ;j = L[j])
 84             {
 85                  U[D[j]] = j;
 86                  D[U[j]] = j;
 87                  ++S[Col[j]];
 88             }
 89     }
 90     bool Dance(int d)
 91     {
 92        if(R[0] == 0 )
 93        {
 94           ansd = d; //答案长度
 95           return true;
 96        }
 97        int c = R[0];
 98        for(int i = R[c];i != 0 ;i = R[i])
 99            if(S[i] < S[c])
100                 c = i ; 
101        remove(c);
102        for(int i = D[c]; i != c;i = D[i])
103        {
104            ans[d] = Row[i];
105            for(int j = R[i]; j != i ;j = R[j])  remove(Col[j]);
106            if(Dance(d+1)) return true;
107            for(int j = L[i]; j != i ;j = L[j])  resume(Col[j]);
108        }
109        resume(c);
110        return false;
111     }
112 };
113 
114 DLX g;
115 int main(){
116    int n , m ; 
117    while(scanf("%d %d",&n,&m) != EOF)
118    {
119       g.init(n,m);
120       int num, j; 
121       for(int i = 1;i <= n;i ++)
122       {
123         scanf("%d",&num);
124         while(num--)
125         {
126           scanf("%d",&j);
127           g.Link(i,j);
128         }
129       }
130       if(!g.Dance(0)) printf("NO\n");
131       else{
132         printf("%d ",g.ansd);
133         for(int i = 0;i < g.ansd;i ++)
134           printf(" %d",g.ans[i]);
135         printf("\n"); 
136       }
137       
138    }
139 return 0;
140 }
View Code

 

转载于:https://www.cnblogs.com/zyue/p/4006220.html

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值