前言

舞蹈链的名字真好玩…


文章目录

  • 前言
  • 一、舞蹈链概述
  • 二、舞蹈链例题
  • 总结

一、舞蹈链概述

舞蹈链 (Dancing links),也叫 DLX ,是由 Donald Knuth 提出的数据结构,目的是快速实现他提出的X算法。X算法是一种递归算法,时间复杂度不确定,深度优先,通过回溯寻找精确覆盖问题所有可能的解

(以上摘自维基百科)

舞蹈链的主要思想来源于双向链表

我们设 l [ x ] l[x] l[x] 表示元素 x x x 的左指针, r [ x ] r[x] r[x] 表示元素 x x x 的右指针

显然,如果想要删除元素 x x x ,我们可以做以下操作

r[l[x]]=r[x]; // x左侧的元素的右指针指向x右侧的元素
l[r[x]]=l[x]; // x右侧的元素的左指针指向x左侧的元素

那恢复元素 x x x 呢? 我们可以发现删除 x x x 的时候, x x x 的左右指针并没有改变,即 l [ x ] l[x] l[x] 和 r [ x ] r[x] r[x] 并没有改变,于是我们可以做以下操作

r[l[x]]=x; // x左侧的元素的右指针重新指向x
l[r[x]]=x; // x右侧的元素的左指针重新指向x

这样如果 x x x 左右两侧没有改变,我们就可以恢复 x x x 所在的位置

那么精确覆盖问题又是什么呢?

给定矩阵,要求选出一个由若干行组成的集合,使得每一列上都有且仅有一个 1 1 1

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}0&0&1&0&1&1&0 \\ 1&0&0&1&0&0&1 \\ 0&1&1&0&0&1&0 \\ 1&0&0&1&0&0&0 \\ 0&1&0&0&0&0&1 \\ 0&0&0&1&1&0&1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

例如该矩阵选出的行为 1 , 4 , 5 1,4,5 1,4,5 行

我们来模拟一下朴素X算法求解的过程

以下过程用红色表示选择了这一行,绿色表示存在冲突的元素,灰色表示删除的行

1.选择第一行

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ 1&0&0&1&0&0&1 \\ 0&1&1&0&0&1&0 \\ 1&0&0&1&0&0&0 \\ 0&1&0&0&0&0&1 \\ 0&0&0&1&1&0&1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

2.标记所有和第一行冲突的元素

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ 1&0&0&1&0&0&1 \\ 0&1&\color{green}1&0&0&\color{green}1&0 \\ 1&0&0&1&0&0&0 \\ 0&1&0&0&0&0&1 \\ 0&0&0&1&\color{green}1&0&1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

3.删除存在冲突的行

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ 1&0&0&1&0&0&1 \\ \color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}0 \\ 1&0&0&1&0&0&0 \\ 0&1&0&0&0&0&1 \\ \color{grey}0&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

4.接着选择第二行

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ \color{red}1&\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}0&\color{red}1 \\ \color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}0 \\ 1&0&0&1&0&0&0 \\ 0&1&0&0&0&0&1 \\ \color{grey}0&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

5.标记与第二行冲突的元素

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ \color{red}1&\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}0&\color{red}1 \\ \color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}0 \\ \color{green}1&0&0&\color{green}1&0&0&0 \\ 0&1&0&0&0&0&\color{green}1 \\ \color{grey}0&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

6.删除存在冲突的行

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ \color{red}1&\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}0&\color{red}1 \\ \color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}0 \\ \color{grey}1&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}0 \\ \color{grey}0&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}0&\color{grey}0&\color{grey}1 \\ \color{grey}0&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​

7.发现没有可以选择的行了,而已选的不满足要求,回溯,选择第四行

( 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 ) \begin{pmatrix}\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}1&\color{red}1&\color{red}0 \\ 1&0&0&1&0&0&1 \\ \color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}0 \\ \color{red}1&\color{red}0&\color{red}0&\color{red}1&\color{red}0&\color{red}0&\color{red}0 \\ 0&1&0&0&0&0&1 \\ \color{grey}0&\color{grey}0&\color{grey}0&\color{grey}1&\color{grey}1&\color{grey}0&\color{grey}1\end{pmatrix} ⎝⎜⎜⎜⎜⎜⎜⎛​010100​001010​101000​010101​100001​101000​010011​⎠⎟⎟⎟⎟⎟⎟⎞​
8.接下来的同理,不断执行,直到找到答案

我们会发现, X X X 算法花了大量的时间在找 1 1 1 ,而且删改很不方便

为了解决这个问题,舞蹈链就产生了

模板题 → \to → P4929 【模板】舞蹈链(DLX)

(注:为了方便讲述,以下引用这篇博客中的图片(感谢图片的作者!))

舞蹈链的结构即交叉十字循环双向链,本文中以数组形式实现链表

int n,m; // 行、列数
int u[MAXN],d[MAXN],l[MAXN],r[MAXN],h[MAXN];
// 每个结点的上下左右指针;每一行的头指针int row[MAXN],col[MAXN],s[MAXN],ansk[MAXN],pos;
// 每个结点原先所在的行、列;每一列的结点个数;ansk记录搜索信息;结点总数

如下图所示

别急!我们一步一步来实现这个复杂的数据结构

首先初始化上方的列头结点

我们可以称列头结点为限制,行头结点为决策 (注:这个做题的时候有用)

void init()
{for(R int i=0; i<=m; i++){l[i]=i-1;r[i]=i+1;u[i]=d[i]=i; }l[0]=m;r[m]=0; //循环链表memset(h,-1,sizeof(h)); //每一行的头结点都为空memset(s,0,sizeof(s)); //每一列的结点数都为0pos=m+1; //已经搭建好了m个列头结点,下一个加入的结点从m+1开始编号
}

接下来,我们来把插入结点的功能完成(注:这里比较复杂,可以感性理解一下)

void link(R int x,R int y)
{s[y]++; //所在的列结点数加1row[pos]=x;col[pos]=y; //记录编号为pos的结点(即新加入的结点)的行和列u[pos]=y; //pos结点的上指针指向插入的列yd[pos]=d[y]; //pos结点的下指针指向插入位置下方的元素u[d[y]]=pos; //插入位置下方的元素的上指针指向pos结点d[y]=pos; //插入位置上方的下指针指向pos结点if(h[x]<0)h[x]=l[pos]=r[pos]=pos;//如果pos结点所在的这一行没有头结点,就自己当else //不然就插入头结点一侧 (下面的就不注释了,和上面插入的方法类似){l[pos]=l[h[x]];r[pos]=h[x];r[l[h[x]]]=pos;l[h[x]]=pos;}pos++; //下一个结点不要标错号了
}

现在我们来完成删除和恢复操作(差不多的)

inline void rm(R int y)
{l[r[y]]=l[y];r[l[y]]=r[y];//删除y列的结点(这个位置已经填满了)for(R int i=d[y]; i!=y; i=d[i])for(R int j=r[i]; j!=i; j=r[j])//删除这一行(冲突的行){d[u[j]]=d[j];u[d[j]]=u[j];s[col[j]]--;//别忘了减1}
}
inline void rv(R int y)
{for(R int i=u[y]; i!=y; i=u[i])for(R int j=l[i]; j!=i; j=l[j])//恢复也是一样的{d[u[j]]=j;u[d[j]]=j;s[col[j]]++;}r[l[y]]=y;l[r[y]]=y;
}

然后可以开始跳舞了
主体部分,就是深度优先搜索

bool dance(R int dep)
{if(!r[0])//所有的列头结点都被选了,说明成功了{for(R int i=0; i<dep; i++)printf("%lld%c",ansk[i]," \n"[i==dep-1]);return 1;}R int y=r[0];for(R int i=r[0]; i; i=r[i])if(s[i]<s[y])y=i;//这里是一个剪枝,每次选择结点最少的列能在一定情况下提高性能rm(y);//删掉这一列for(R int i=d[y]; i!=y; i=d[i])//每次选择这列中的一行{ansk[dep]=row[i];for(R int j=r[i]; j!=i; j=r[j])rm(col[j]);//删掉这一行中所有结点(这一行冲突)if(dance(dep+1))return 1;//成功就返回for(R int j=l[i]; j!=i; j=l[j])rv(col[j]);//恢复}rv(y);return 0;
}

如果您不太理解的话,可以看看下面的动图(注:其实和之前模拟的有些相似)

算法执行过程 (注:图片是这篇博客的)

最终的答案即下图 (选择 1 , 4 , 5 1,4,5 1,4,5 )

最后贴上完整代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define R register
#define MAXN 250505
template<typename T>inline void read(R T &k)
{R char ch=getchar(); R T x=0,f=1;while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}k=x*f;
}
int n,m;
int u[MAXN],d[MAXN],l[MAXN],r[MAXN],h[MAXN];
int row[MAXN],col[MAXN],s[MAXN],ansk[MAXN],pos;
void init()
{for(R int i=0; i<=m; i++){l[i]=i-1;r[i]=i+1;u[i]=d[i]=i;}l[0]=m;r[m]=0;memset(h,-1,sizeof(h));memset(s,0,sizeof(s));pos=m+1;
}
void link(R int x,R int y)
{s[y]++;row[pos]=x;col[pos]=y;u[pos]=y;d[pos]=d[y];u[d[y]]=pos;d[y]=pos;if(h[x]<0)h[x]=l[pos]=r[pos]=pos;else{l[pos]=l[h[x]];r[pos]=h[x];r[l[h[x]]]=pos;l[h[x]]=pos;}pos++;
}
inline void rm(R int y)
{l[r[y]]=l[y];r[l[y]]=r[y];for(R int i=d[y]; i!=y; i=d[i])for(R int j=r[i]; j!=i; j=r[j]){d[u[j]]=d[j];u[d[j]]=u[j];s[col[j]]--;}
}
inline void rv(R int y)
{for(R int i=u[y]; i!=y; i=u[i])for(R int j=l[i]; j!=i; j=l[j]){d[u[j]]=j;u[d[j]]=j;s[col[j]]++;}r[l[y]]=y;l[r[y]]=y;
}
bool dance(R int dep)
{if(!r[0]){for(R int i=0; i<dep; i++)printf("%lld%c",ansk[i]," \n"[i==dep-1]);return 1;}R int y=r[0];for(R int i=r[0]; i; i=r[i])if(s[i]<s[y])y=i;rm(y);for(R int i=d[y]; i!=y; i=d[i]){ansk[dep]=row[i];for(R int j=r[i]; j!=i; j=r[j])rm(col[j]);if(dance(dep+1))return 1;for(R int j=l[i]; j!=i; j=l[j])rv(col[j]);}rv(y);return 0;
}
signed main()
{read(n);read(m);init();for(R int i=1; i<=n; i++)for(R int j=1,t; j<=m; j++){read(t);if(t)link(i,j);}if(!dance(0))puts("No Solution!");return 0;
}

二、舞蹈链例题

如果您看到这里,还是很明白的话,那么我们来讲个例题

题目链接:SP13980 SUDOGOB - Sudoku goblin

题意:给定一个 9 × 9 9 \times 9 9×9 的数独,输出可填的方案数,多组数据

选择这个例题当然不是让你写暴搜的

首先考虑决策

每个格子上填数字,至多有 9 × 9 × 9 = 729 9\times 9\times 9 = 729 9×9×9=729 种决策

再考虑限制

  1. 每个点只能填一个数
  2. 每行一个数只能填一次
  3. 每列一个数只能填一次
  4. 每个九宫格一个数只能填一次

限制数为 9 × 9 × 4 = 324 9\times 9 \times 4 = 324 9×9×4=324

对于精准覆盖问题,我们本质上是在选择若干决策,使其恰好满足所有限制条件

因此这题可以用 DLX 求解

那么 MAXN只要开到 729*324 就行了(注:不过开大点保险)

这题唯一的细节是插入结点的行、列,还是很简单的题目

代码如下

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define R register
#define MAXN (729*324+6666)
int Q;
bool suc;
int a[25][25];
int ans[25][25],Ans;
int h[MAXN],l[MAXN],r[MAXN],u[MAXN],d[MAXN];
int row[MAXN],col[MAXN],pos,s[MAXN],ansk[MAXN];
template<typename T>inline void read(R T &k)
{R char ch=getchar();R T x=0,f=1;while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}k=x*f;
}
inline void init()
{int m=324;Ans=0;suc=0;for(R int i=0; i<=m; i++){l[i]=i-1;r[i]=i+1;u[i]=d[i]=i;}l[0]=m;r[m]=0;memset(s,0,sizeof(s));memset(h,-1,sizeof(h));pos=m+1;
}
inline void link(R int x,R int y)
{s[y]++;row[pos]=x;col[pos]=y;u[pos]=y;d[pos]=d[y];u[d[y]]=pos;d[y]=pos;if(h[x]<0)h[x]=l[pos]=r[pos]=pos;else{l[pos]=l[h[x]];r[pos]=h[x];r[l[h[x]]]=pos;l[h[x]]=pos;}++pos;
}
inline void rm(R int y)
{r[l[y]]=r[y];l[r[y]]=l[y];for(R int i=d[y]; i!=y; i=d[i])for(R int j=r[i]; j!=i; j=r[j]){u[d[j]]=u[j];d[u[j]]=d[j];s[col[j]]--;}
}
inline void rv(R int y)
{for(R int i=u[y]; i!=y; i=u[i])for(R int j=l[i]; j!=i; j=l[j]){u[d[j]]=j;d[u[j]]=j;s[col[j]]++;}l[r[y]]=y;r[l[y]]=y;
}
void dance(R int dep)
{if(!r[0]){Ans++;if(Ans>1)suc=1;for(R int i=0; i<dep&&!suc; i++){R int x=(ansk[i]-1)/9/9+1;R int y=(ansk[i]-1)/9%9+1;R int z=(ansk[i]-1)%9+1;ans[x][y]=z;}return;}R int y=r[0];for(R int i=r[0]; i!=0; i=r[i])if(s[i]<s[y])y=i;rm(y);for(R int i=d[y]; i!=y; i=d[i]){ansk[dep]=row[i];for(R int j=r[i]; j!=i; j=r[j])rm(col[j]);dance(dep+1);for(R int j=l[i]; j!=i; j=l[j])rv(col[j]);}rv(y);
}
signed main()
{read(Q);while(Q--){init();for(R int i=1; i<=9; i++)for(R int j=1; j<=9; j++){read(a[i][j]);R int &t=a[i][j];for(R int k=1; k<=9; k++){if(t!=k&&t!=0)continue;R int o=(i-1)*9*9+(j-1)*9+k;R int c1=81*0 + (i-1)*9+(j-1)+1;R int c2=81*1 + (i-1)*9+k;R int c3=81*2 + (j-1)*9+k;R int c4=81*3 + ((i-1)/3*3+(j-1)/3)*9+k;link(o,c1);link(o,c2);link(o,c3);link(o,c4);}}dance(0);if(!Ans){puts("0");continue;}printf("%lld\n",Ans);for(R int i=1; i<=9&&!suc; i++)for(R int j=1; j<=9; j++)printf("%lld%c",ans[i][j]," \n"[j==9]);}return 0;
}

当然,如果您有兴趣的话,可以去做下这道题

题目链接:SP1110 SUDOKU - Sudoku

这道题就是上一题的加强版,其实没什么区别,如果您理解了例题的话,这题就很简单了


总结

本文介绍了舞蹈链

转载请说明出处

浅谈舞蹈链(DLX)相关推荐

  1. 浅谈区块链技术应用场景

    浅谈区块链技术应用场景 摘要 一,区块链技术简介 二,区块链技术基础 1. 点对点之间传输信息的网络 2. 非对称加密技术 3. 共识机制 三,基于软件层面区块链技术应用场景 应用层 区块链技术与身份 ...

  2. 浅谈区块链数字货币发展现状

    浅谈区块链数字货币发展现状 前言 因为自己这学期在学习金融学的相关知识,在通过两门课,即区块链以及货币银行学的比较,对于区块链技术产生的数字货币对当前传统金融体系的冲击有自己的一点看法,故本次作业主要 ...

  3. 广积粮,缓称王——浅谈区块链项目的护城河

    广积粮,缓称王--浅谈区块链项目的护城河这里写自定义目录标题 最近,一个二次元视频网站项目火遍圈内,上线即暴跌.把各类投资者割的找不着北了.又一个拥有"强大"社区的项目上演见光死, ...

  4. 猿创征文|浅谈区块链-区块链是什么?

    文章目录 前言 基本概念 工作原理 底层架构 共识机制 前言 区块链一词很早就进入了我的视野,一顿操作猛如虎后,发现可意会,但难以用文字阐述清楚,本文也是在草稿箱不断修修改改,尽量用通俗的语言进行梳理 ...

  5. 蒟蒻浅谈树链剖分之一——两个dfs操作

    树链剖分,顾名思义就是将树形的结构剖分成链,我们以此便于在链上操作 首先我们需要明白在树链剖分中的一些概念 重儿子:某节点所有儿子中子树最多的儿子 重链:有重儿子构成的链 dfs序:按重儿子优先遍历时 ...

  6. 舞蹈链(DLX)模板

    const int N=1e3+100;//行数const int M=1e3+100;//列数const int NODE=5e5+100;//节点数struct DancingLink{int n ...

  7. P4929-[模板]舞蹈链(DLX)

    正题 题目链接:https://www.luogu.com.cn/problem/P4929 题目大意 n∗mn*mn∗m的矩形有0/10/10/1,要求选出若干行使得每一列有且仅有一个111. 解题 ...

  8. 浅谈区块链的格局审视和被遗忘的权利

    被遗弃的支配权指的是欧盟国家(EU)新上市的一般个人信息保护规章(GDPR)中要求的第17条,而且早已于17年5月28日起效,受权所有人能够改正乃至删掉危害别人的本人数据信息和信息内容,假如出自于搜集 ...

  9. 浅谈区块链技术对未来行业的影响

    2017年是比特币和其他加密货币蓬勃发展的一年,而2018年是区块链对技术世界颠复迈出的第一步.很多建立在区块链上的项目都在2019年发布他们的产品,并为区块链开发新的功能,我们将会看到很多不同的应用 ...

最新文章

  1. 顶会「扩招」,一地鸡毛:ICLR2020近半数审稿人未发过相关论文
  2. 第四届中国国际大数据大会务实推进应用落地
  3. hadoop实战--搭建开发环境及编写Hello World
  4. java.lang.ClassNotFoundException: org/apache/xerces/parsers/SAXParser
  5. MIT Scheme 使用 Edwin
  6. HTML怎么做类似QQ聊天气泡,h5实现QQ聊天气泡的实例介绍
  7. CKeditor自定义上传图片功能
  8. 计算机管理器win8,Win8如何快速打开资源管理器,Win8快速打开计算机操作方法
  9. (一) pyhon 基础语法(数值 字符串 元组 列表 字典)
  10. java 实现word转txt
  11. 机器学习笔记:训练集、验证集与测试集
  12. 计算机232接口接线图,RS485电缆(电脑和变频器的连线)如何接法!RS232接法知道的2-3 3-2 5-5-工业支持中心-西门子中国...
  13. 阿帕奇服务器查看本地网页,如何在Apache Web服务器上查看当前连接?
  14. 机器人示教器国产终端,功能图解
  15. windows 10 Tera Term显示乱码
  16. 最小采样频率计算公式_AD5933使用外部时钟获得更低的分析频率
  17. wamp升级后运行提示php-win.exe无法找到入口
  18. “携手共建互联网安全生态”研讨会在京召开
  19. python金融分析小知识(23)——matplotlib面向对象绘制股票收盘价曲线
  20. p5.js动态图形临摹以及拓展

热门文章

  1. 2018苹果发布会新品 是如何成为众商家的追热点目标
  2. 【ML】range、arange和linspace函数
  3. 用DIV+CSS技术设计我的家乡网站(web前端网页制作课作业)南宁绿城之都
  4. java实现阿里大于短信发送服务
  5. 解决ubuntu12.04安装air微博错误
  6. CentOS7安装教程
  7. 跟我学UDS(ISO14229) ———— 0x2C(DynamicallyDefineDataIdentifier)
  8. 做计算机视觉对电脑配置的要求,计算机视觉环境配置
  9. 使用Angular的网站
  10. CSS - 文本文字 增加外框、阴影、边框