浅入 dancing links x(舞蹈链算法)
abastract:利用dancing links 解决精确覆盖问题,例如数独,n皇后问题;以及重复覆盖问题。
要学习dacning links 算法,首先要先了解该算法适用的问题,精确覆盖问题和重复覆盖问题等,下面先了解精确覆盖问题和重复覆盖问题。
精确覆盖问题
何为精确覆盖问题
在一个全集X中若干子集的集合为S,精确覆盖(Exactcover)是指,S的子集S*,满足X中的每一个元素在S*中恰好出现一次。
定义
S*中任意两个集合没有交集,即X中的元素在S*中出现最多一次
S*中集合的全集为X,即X中的元素在S*中出现最少一次
合二为一,即X中的元素在S*中出现恰好一次。
N={}
O={1,3}
E={2,4}
P={2,3}.
其中一个子集{O,E}是X的一个精确覆盖,因为O={1,3}而E={2,4}的并集恰好是X={1,2,3,4}。同理,{N,O,E}也是X.的一个精确覆盖。空集并不影响结论。
精确覆盖问题的表示方式
一般的,我们用一个集合s包含s中的元素的单向关系表示精确覆盖问题。常用的有以下两种方法:
- 矩阵表示法
包含关系可以用一个关系矩阵表示。.矩阵每行表示S的一个子集,每列表示X中的一个元素。矩阵行列交点元素为1表示对应的元素在对应的集合中,不在则为0。
通过这种矩阵表示法,求一个精确覆盖转化为求矩阵的若干个行的集合,使每列有且仅有一个1。同时,该问题也是精确覆盖的典型例题之一。
下表为其中一个例子:
S*={B,D,F}便是一个精确覆盖。
- 图论表示法
可将精确覆盖问题转化为一个二分图,左侧为集合,右侧为元素,左侧集合若与右侧元素有包含关系则连边,通过将左侧节点与其所有边保留与否求解一个右侧的每一个节点恰好有一条边的匹配。
重复覆盖问题
即选取一个01矩阵中的几行,使这几行组成的新矩阵的每一列至少有一个1。 该问题在精确覆盖问题上减少了一个约束条件。
接下来就是dancing links x算法了。
Dancing Links X 算法
历史
X算法是高德纳提出的解决精确覆盖问题的算法,而dancing links X算法则是DonKnuth(《计算机程序设计艺术》的作者)提出的对X算法的一种高效实现,这种实现建立在如上所说的矩阵表示法上。
算法思想
由如上精确覆盖问题的矩阵表示法中,我们知道dancing links x 是用来求解一个 01矩阵中选取哪几行可以使得这几行每一列都有且仅有一个1(就是每个元素在这几个子集里有且仅有出现过一次)。
先不管他的实际意义,我们需要做的就是在一个01矩阵的选取某几行使之符合上述条件。
我们很容易就想到枚举,然后判断符不符合条件,但是这个做法实在是太消耗时间。
dacing links x就是一个高效的求解该类问题的算法,而这种算法,基于交叉十字循环双向链的数据结构。
例如:如下的矩阵
就包含了这样一个集合(第1、4、5行)
如何利用给定的矩阵求出相应的行的集合呢?我们采用回溯法
先假定选择第1行,如下所示:
如上图中所示,红色的那行是选中的一行,这一行中有3个1,分别是第3、5、6列。
由于这3列已经包含了1,故,把这三列往下标示,图中的蓝色部分。蓝色部分包含3个1,分别在2行中,把这2行用紫色标示出来
根据定义,同一列的1只能有1个,故紫色的两行,和红色的一行的1相冲突。
那么在接下来的求解中,红色的部分、蓝色的部分、紫色的部分都不能用了,把这些部分都删除,得到一个新的矩阵
行分别对应矩阵1中的第2、4、5行
列分别对应矩阵1中的第1、2、4、7列
于是问题就转换为一个规模小点的精确覆盖问题
在新的矩阵中再选择第1行,如下图所示
还是按照之前的步骤,进行标示。红色、蓝色和紫色的部分又全都删除,导致新的空矩阵产生,而红色的一行中有0(有0就说明这一列没有1覆盖)。说明,第1行选择是错误的
那么回到之前,选择第2行,如下图所示
按照之前的步骤,进行标示。把红色、蓝色、紫色部分删除后,得到新的矩阵
行对应矩阵2中的第3行,矩阵1中的第5行
列对应矩阵2中的第2、4列,矩阵1中的第2、7列
由于剩下的矩阵只有1行,且都是1,选择这一行,问题就解决
于是该问题的解就是矩阵1中第1行、矩阵2中的第2行、矩阵3中的第1行。也就是矩阵1中的第1、4、5行()
(例子引用自http://www.cnblogs.com/grenet/p/3145800.html)
而对于重复覆盖问题,在选定某一行之后只需删除该行含1的所在列,并不需要再删除所在列上含1的行。
2016-08-21 21:00:15
Example1:HUST 1017
裸精确覆盖问题,问题如下:
1017 - Exact cover
题目描述:
There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find out the selected rows.输入There are multiply test cases. First line: two integers N, M; The following N lines: Every line first comes an integer C(1 <= C <= 100), represents the number of 1s in this row, then comes C integers: the index of the columns whose value is 1 in this row.输出First output the number of rows in the selection, then output the index of the selected rows. If there are multiply selections, you should just output any of them. If there are no selection, just output "NO".
样例输入
6 7
3 1 4 7
2 1 4
3 4 5 7
3 3 5 6
4 2 3 6 7
2 2 7
样例输出
3 2 4 6
提示来源
dupeng
裸精确覆盖问题,直接用dancing links 做。
#include<cstdio>
#include<iostream>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
#define clrlow(x) memset(x,-1,sizeof(x))
#define maxnode 1001010
#define maxn 1010
using namespace std;
struct DLX{
int n,m;
int U[maxnode],D[maxnode],L[maxnode],R[maxnode],col[maxnode],row[maxnode];
int H[maxn];
int ansed,ans[maxn],size;
void init(int _n,int _m)
{
n=_n;
m=_m;
for(int i=;i<=m;i++)
{
U[i]=i;
D[i]=i;
L[i]=i-;
R[i]=i+;
col[i]=i;
row[i]=;
}
L[]=m;
R[m]=;
size=m;
clrlow(H);
clr(ans);
ansed=;
return ;
}
void push(int r,int c)
{
size++;
D[size]=D[c];
U[size]=c;
U[D[c]]=size;
D[c]=size;
row[size]=r;
col[size]=c;
if(H[r]<)
{
H[r]=size;
R[size]=L[size]=size;
}
else
{
L[size]=H[r];
R[size]=R[H[r]];
L[R[H[r]]]=size;
R[H[r]]=size;
}
}
void del(int c)
{
R[L[c]]=R[c];
L[R[c]]=L[c];
for(int i=D[c];i!=c;i=D[i])
for(int j=R[i];j!=i;j=R[j])
{
D[U[j]]=D[j];
U[D[j]]=U[j];
}
return ;
}
void reback(int c)
{
for(int i=U[c];i!=c;i=U[i])
for(int j=L[i];j!=i;j=L[j])
{
D[U[j]]=j;
U[D[j]]=j;
}
R[L[c]]=c;
L[R[c]]=c;
return ;
}
bool dancing(int dep)
{
if(R[]==)
{
ansed=dep;
return true;
}
int c=R[];
del(c);
for(int i=D[c];i!=c;i=D[i])
{
ans[dep]=row[i];
for(int j=R[i];j!=i;j=R[j])
del(col[j]);
if(dancing(dep+))
return true;
for(int j=L[i];j!=i;j=L[j])
reback(col[j]);
}
return false;
}
}dlx;
int main()
{
int n,m,p,k;
while(scanf("%d%d",&n,&m)==)
{
dlx.init(n,m);
for(int i=;i<=n;i++)
{
scanf("%d",&p);
for(int j=;j<=p;j++)
{
scanf("%d",&k);
dlx.push(i,k);
}
}
if(!dlx.dancing())
printf("NO\n");
else
{
printf("%d",dlx.ansed);
for(int i=;i<dlx.ansed;i++)
printf(" %d",dlx.ans[i]);
printf("\n");
}
}
return ;
}
除此之外,运用这个dancing links 的这个模板,还可以解决数独,n皇后问题。
浅谈数独解法
我们在做数独时一般会使用枚举法。在某个格子枚举当前情况下的所有可填入数字,而在枚举其中一个可填入数字后递归到下一层,也就是下一个格子,枚举上一个格子数字确定下来的九宫格在该格子的所有可填入数字,以此类推。直到九宫格完全填满时,这时候的解为该九宫格的一个可行解,可继续递归返回上一层寻找下一个可行解。这个做法效率不错,但是若直接枚举,写起来就又臭又长(好吧我承认其实DLX也挺长的),若九宫格过于稀疏,该做法的时间效率也会指数级上升。我们选择用DLX把每一个已填格子和未填格子的信息转化成行,接下来dance一遍找出符合条件的行,再转化回九宫格信息,就是一个可行解了。最多729行进行DLX(9*9*9,后面你会明白的),速度较直接枚举也快很多,除去DLX的结构体,其他代码长度也比直接枚举短很多(打模板比较快hhh)。
那么怎么把九宫格上的信息转化成行呢? 首先数独中可行的解需满足:每一行,每一列,每一个宫里面不能有相同的数字,且只能使用1-9这九个数字。
把它转化为符合精确覆盖问题的条件,即为:
- 每一个格只能填一个数字。
- 每个数字在每一行只能出现一次。
- 每个数字在每一列只能出现一次。
- 每个数字在每一宫只能出现一次。
对于第一个条件:
第一列表示填入(1,1)这一格。
第二列表示填入(1,2)这一格。
第三列表示填入(1,3)这一格。
……
第(m-1)*9+n列表示填入(m,n)这一格。(1<=m<=9,1<=n<=9)
……
第9*9-1列表示填入(9,8)这一格。
第9*9列表示填入(9,9)这一格。
设inf1=81;
以此类推……
第二个条件:
第inf+1列表示在第一行填入1。
第inf+2列表示在第一行填入2。
第inf+3列表示在第一行填入3。
……
第inf+(n-1)*9+m列表示在第n行填入m(1<=n<=9,1<=m<=9)。
……
第inf+9*9表示在第九行填入9。
设inf2=inf1+81;
对于第三个条件也是如此,inf3=inf2+81;
对于第四个条件,inf4=inf3+81;
至此,已经把所有的条件都转化成了列。
而对于一个有数字的格子(假设位于(m,n)数字为k,位于第p宫)只需把它转化为一行,该行于(m-1)*9+n,inf1+(m-1)*9+k,inf2+(n-1)*9+k,inf3+(p-1)*9+k这四列为1,其余为0。
对于一个没有数字的格子(假设位于(m',n')第p'宫),则需把他转化为九行,分别代表在这一格填入1-9各个数字,每一列的填列原理和有数字的格子一样。
在把所有的格子转化完毕后,先把所有确定的有数字的格子的行以及该行含1的列以及该列上含1的行从矩阵中删除,然后dance一遍,找出符合的行,再把行转化成每个格子的信息,填入九宫格中,就是符合的一个解了。
2016-08-27 17:07:53
n皇后解法
类似于数独问题,在n皇后问题中,不冲突的n皇后的棋盘上符合以下五个个条件:
- 每一个格子最多只能有一个皇后。
- 每一行最多只能有一个皇后。
- 每一列最多只能有一个皇后。
- 每一个从左上往右下的斜边最多只能有一个皇后。
- 每一个从右上往左下的斜边最多只能有一个皇后。
这五个条件看起来不太好用dlx的做法去做,但如果把整个棋盘中有皇后的位置用1表示,没有皇后的位置用1表示,则可以转化为:
- 每个格子只能填一个数字。
- 每一行有且仅能填一个1。
- 每一列有且仅能填一个1。
- 每一个从左上往右下的斜边有且仅能填一个1。
- 每一个从右上往左下的斜边有且仅能填一个1。
按照数独的过程进行DLX,找出填1的行数大于等于n的解。等于n的解即为n皇后问题的解,大于n的解删去几行使填1的行数为n即为n皇后问题的解。
重复覆盖问题
顾名思义,即为在01矩阵中,选出几行,使得在这几行组成的新矩阵中,每一列都有1。
下面是hdu上一个重复覆盖的二分问题,并且给出重复覆盖问题的代码部分:
Example2:hdu 2295
Radar
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2280 Accepted Submission(s): 897
Each of the last M lines consists of the coordinate of a radar station.
All coordinates are separated by one space.
Technical Specification
1. 1 ≤ T ≤ 20
2. 1 ≤ N, M ≤ 50
3. 1 ≤ K ≤ M
4. 0 ≤ X, Y ≤ 1000
该题用二分查找radar的半径,然后用重复覆盖的DLX进行最多选取k行该半径是否完全覆盖所有城市的判断(f()函数和dep一起判断),最后精确到小数点后六位。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define clr(x) memset(x,0,sizeof(x))
#define clrlow(x) memset(x,-1,sizeof(x))
#define maxnode 3000
#define maxn 60
using namespace std;
struct DLX//dancing links
{
int U[maxnode],D[maxnode],L[maxnode],R[maxnode],col[maxnode],row[maxnode];//元素上下左右对应列对应行的指针
int S[maxn],H[maxn],V[maxn];//S为每列元素个数,H指向每行末尾的元素,V是dep()函数的标记数组。
int n,m,size,all;//all为解的行数的最大值
void init(int _n,int _m,int _all)
{
n=_n;
m=_m;
all=_all;
for(int i=;i<=m;i++)
{
L[i]=i-;
R[i]=i+;
U[i]=i;
D[i]=i;
row[i]=;
col[i]=i;
}
clr(S);
clrlow(H);
L[]=m;
R[m]=;
size=m;
return ;
}
//初始化
void push(int r,int c)
{
D[++size]=D[c];
col[size]=U[size]=c;
U[D[c]]=size;
D[c]=size;
row[size]=r;
S[c]++;
if(H[r]<)
{
H[r]=L[size]=R[size]=size;
}
else
{
L[size]=H[r];
R[size]=R[H[r]];
L[R[H[r]]]=size;
R[H[r]]=size;
}
return ;
}
//加入元素
void del(int c)
{
S[col[c]]--;
for(int i=D[c];i!=c;i=D[i])
{
R[L[i]]=R[i];
L[R[i]]=L[i];
S[col[i]]--;
}
return ;
}
//删除一列
void reback(int c)
{
for(int i=U[c];i!=c;i=U[i])
{
S[col[R[L[i]]=L[R[i]]=i]]++;
}
S[col[c]]++;
return ;
}
//恢复一列
int dep( )
{
clr(V);
int deep=;
for(int i=R[];i!=;i=R[i])
if(!V[i])
{
deep++;
for(int j=D[i];j!=i;j=D[j])
for(int k=R[j];k!=j;k=R[k])
V[col[k]]=;
}
return deep;
}
//之后到达的最大深度
//d为当前深度
bool dancing(int d)
{
if(d+dep()>all) return false;
int c=R[];
if(c==)
{
return d<=all;
}
for(int i=R[];i!=;i=R[i])
if(S[i]<S[c])
c=i;
for(int i=D[c];i!=c;i=D[i])
{
del(i);
for(int j=R[i];j!=i;j=R[j])
del(j);
if(dancing(d+)) return true;
for(int j=L[i];j!=i;j=L[j])
reback(j);
reback(i);
}
return false;
}
//dancing
}dlx;
struct point
{
int x,y;
}station[maxn],city[maxn];
double dis(point a,point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main()
{
int n,m,k,kase;
double lt,rt,mid;
double eps=1e-;
scanf("%d",&kase);
while(kase--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;i++)
scanf("%d%d",&city[i].x,&city[i].y);
for(int i=;i<=m;i++)
scanf("%d%d",&station[i].x,&station[i].y);
lt=;
rt=1e8;
while(rt-lt>=eps)
{
dlx.init(m,n,k);
mid=(rt+lt)/;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
if(dis(city[j],station[i])<mid*mid-eps)
dlx.push(i,j);
if(dlx.dancing())
rt=mid-eps;
else
lt=mid+eps;
}
printf("%.6lf\n",lt);
}
return ;
}
FZU上一道练手题
Problem 1686 神龙的难题
Accept: 717 Submit: 2140
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉就是这样的一个人.她骑着她的坐骑,神龙米格拉一起消灭干扰人类生存的魔物,维护王国的安定.艾米莉希望能够在损伤最小的前提下完成任务.每次战斗前,她都用时间停止魔法停住时间,然后米格拉他就可以发出火球烧死敌人.米格拉想知道,他如何以最快的速度消灭敌人,减轻艾米莉的负担.
Input
数据有多组,你要处理到EOF为止.每组数据第一行有两个数,n,m,(1<=n,m<=15)表示这次任务的地区范围. 然后接下来有n行,每行m个整数,如为1表示该点有怪物,为0表示该点无怪物.然后接下一行有两个整数,n1,m1 (n1<=n,m1<=m)分别表示米格拉一次能攻击的行,列数(行列不能互换),假设米格拉一单位时间能发出一个火球,所有怪物都可一击必杀.
Output
输出一行,一个整数,表示米格拉消灭所有魔物的最短时间.
Sample Input
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
2 2
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
2 2
Sample Output
1
Source
FOJ月赛-2009年2月- TimeLoop
依旧是重复覆盖问题模板
#include<cstdio>
#include<iostream>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
#define clrlow(x) memset(x,-1,sizeof(x))
#define maxm (15*15+10)
#define maxn (15*15+10)
#define maxnode maxn*maxm
#define INF 1000000000
using namespace std;
struct DLX
{
int size,n,m;
int D[maxnode],U[maxnode],L[maxnode],R[maxnode],row[maxnode],col[maxnode];
int H[maxn],S[maxm];
int ansed;
void init(int _n,int _m)
{
n=_n;
m=_m;
size=m;
for(int i=;i<=m;i++)
{
D[i]=i;
U[i]=i;
R[i]=i+;
L[i]=i-;
row[i]=;
col[i]=i;
S[i]=;
}
L[]=m; R[m]=;
for(int i = ;i <= n;i++)H[i] = -;
ansed=INF;
return ;
}
void push(int r,int c)
{
++S[col[++size]=c];
row[size]=r;
D[size]=D[c];
U[size]=c;
U[D[c]]=size;
D[c]=size;
if(H[r]<)
{
L[size]=R[size]=size;
H[r]=size;
}
else
{
R[size]=R[H[r]];
L[size]=H[r];
L[R[H[r]]]=size;
R[H[r]]=size;
}
return;
}
void del(int p)
{
for(int i=D[p];i!=p;i=D[i])
{
R[L[i]]=R[i];
L[R[i]]=L[i];
}
return ;
}
void remove(int p)
{
for(int i=U[p];i!=p;i=U[i])
{
R[L[i]]=L[R[i]]=i;
}
return ;
}
bool v[maxm];
int dis()
{
int ans=;
for(int i=;i<=m;i++) v[i]=;
for(int i=R[];i!=;i=R[i])
if(!v[i])
{
ans++;
for(int j=D[i];j!=i;j=D[j])
for(int k=R[j];k!=j;k=R[k])
v[col[k]]=;
}
return ans;
}
void dancing(int dep)
{
if(dep+dis()>=ansed) return;
if(R[]==)
{
if(dep<ansed) ansed=dep;
return ;
}
int c=R[];
for(int i=R[];i!=;i=R[i])
if(S[i]<S[c])
c=i;
for(int i=D[c];i!=c;i=D[i])
{
del(i);
for(int j=R[i];j!=i;j=R[j])
del(j);
dancing(dep+);
for(int j=L[i];j!=i;j=L[j])
remove(j);
remove(i);
}
return ;
}
}dlx;
int n,m,n1,m1,a[maxn][maxm],num[maxn][maxm],inf;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
inf=;
clr(a);
clr(num);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==) num[i][j]=(++inf);
}
dlx.init(n*m,inf);
scanf("%d%d",&n1,&m1);
inf=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
inf++;
for(int k=i;k<i+n1 && k<=n;k++)
for(int l=j;l<j+m1 && l<=m;l++)
if(num[k][l])
dlx.push(inf,num[k][l]);
}
dlx.dancing();
printf("%d\n",dlx.ansed);
}
return ;
}
浅入 dancing links x(舞蹈链算法)的更多相关文章
- 算法帖——用舞蹈链算法(Dancing Links)求解俄罗斯方块覆盖问题
问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形.如何用计算机求解? 解决这类问题的方法不一而足,然而核心思想都是穷举法,不同的方法仅仅是对穷举法进行了优化 用13块不同形状的俄罗斯方块(每个 ...
- 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...
- Dancing Links算法(舞蹈链)
原文链接:跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题 作者:万仓一黍 出处:http://grenet.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,但 ...
- 转载 - 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
出处:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 ...
- [转] 舞蹈链(Dancing Links)——求解精确覆盖问题
转载自:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个 ...
- DLX舞蹈链 hdu5046
题意: 在N个城市选出K个城市,建飞机场(1 ≤ N ≤ 60,1 ≤ K ≤ N),N个城市给出坐标,选择这K个机场,使得从城市到距离自己最近的机场的 最大的距离 最小. 输出这个最小值. 思路: ...
- 算法实践——舞蹈链(Dancing Links)算法求解数独
在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...
- 转载 - 算法实践——舞蹈链(Dancing Links)算法求解数独
出处:http://www.cnblogs.com/grenet/p/3163550.html 在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dan ...
- Dancing Links and Exact Cover
1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...
随机推荐
- less初识
一种 动态 样式 语言. LESS 将 CSS 赋予了动态语言的特性,如 变量, 继承,运算, 函数. LESS 既可以在 客户端 上运行 (支持IE 6+, Webkit, Firefox),也可以 ...
- Swift图书展示项目笔记
1.Swift语言特点 Extensions(扩展):就是向一个已有的类.结构体.枚举类型或者协议类型添加新功能.这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模) map: 得到一个 ...
- 【转】python直接运行tcl脚本
python中调用tcl是通过加载TkInter来实现的. from Tkinter import Tcl tcl = Tcl() tcl.eval('source tu.tcl') tcl.eval ...
- odoo 打印格式中 打印第一个数据默认
<table style="width:100%;"> <tr> <td style="word-wrap:break-word;width ...
- OSS介绍
1 基本概念介绍 1.1 存储空间(Bucket) 存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间.您可以设置和修改存储空间属性用来控制地域.访问权限.生命周期等, ...
- 搭建 Guacamole 并解决各种坑和创建不了虚拟驱动器导致无法实现文件传输的方法
系统类型版本:centos7 64位 结果:最终跑通了项目并且实现了虚拟驱动器的文件传输功能,添加了中文支持 反思总结: 先查看官方文档的Q&A,找找有没有类似的错误,然后如果有错误日志或者现 ...
- springtest mapper注入失败问题解决 {@org.springframework.beans.factory.annotation.Autowired(required=true)}
花费了一下午都没有搜索到相关解决方案的原因,一是我使用的 UnsatisfiedDependencyException 这个比较上层的异常(在最前面)来进行搜索, 范围太广导致没有搜索到,而且即便是有 ...
- 简单测评拨号VPS——云立方&淘宝卖家
做爬虫的同学不可避免地要使用代理IP,除了各网站公布的免费代理IP外,我们还可以选择拨号VPS,本文简单对两家(类)拨号VPS提供商进行测评,如有差错,欢迎指出,非常感谢. 使用过程 云立方 第一次听 ...
- Appium+python自动化4-元素定位uiautomatorviewer
前言 环境搭建好了,下一步元素定位,元素定位本篇主要介绍如何使用uiautomatorviewer,通过定位到页面上的元素,然后进行相应的点击等操作. uiautomatorviewer是androi ...
- Loadrunner 面试常见问题
三大组件: 脚本生成器,录制和调试脚本 . 控制台,设置运行和资源场景 结果分析器,将测试结果数据以不同的图表呈现,便于性能分析 工作原理: 录制:根据不同协议,记录下客户端和服务器二者之间的对话,生 ...