一篇不错的 Dancing Links 介绍文章 [转]

acm dancing link 神奇的数据结构!用来处理数独问题的巧妙数据结构。。。。 立即下载

 

 

 

              Dancing Links 在搜索中的应用 

 

                                        momodi 

 

                                   2008 年7 月8  日 

 

 

 

 

 

1.1    Dancing Links是什么 

 

     Dancing Links  是knuth 在近几年写的一篇论文,在我看来是一类搜索 

 

问题的通用优化, 因此我把它写下来,希望能在竞赛中得到一定的应用。 

 

1.2    Dancing  Links的主要原理是什么 

 

     Dancing Links 主要是用双向十字链表来存储稀疏矩阵,来达到在搜索 

 

中的优化。在搜索问题中,所需要存储的矩阵往往随着递归的加深会变得越 

 

来越稀疏,这种情况用Dancing Links 来存储矩阵,往往可以取得非常好的 

 

效果。 

 

1.3    这篇论文与knuth论文的不同 

 

     本篇论文是对Dancing Links 在竞赛的应用的一个介绍,并列举了几个 

 

竞赛中的例题。原文可以在此下载到: 

 

     http://www.ocf.berkeley.edu/ jchu/publicportal/sudoku/0011047.pdf 

 

     相对于本文,我更建议去读者去看knuth的原文,本文可以当作一个参 

 

考。本文还介绍了Sukudo问题和一个Dancing Links的一个变种问题。 

 

                             2     双向链表 

 

2.1    双向链表的存储结构 

 

     双向链表的存储结构往往是有一个空的结点来表示头指针。然后每一 

 

个结点有一个pre值域和一个next值域。如果是十字链表的话,结点中指针 

 

的值域会变成四个。 

 

2.2    双向链表的应用 

 

     众所周知,在单向链表中删除一个结点是非常麻烦,而且低效的。双向 

 

链表有着优美的结构,可以方便的删除任意一个结点。有如下操作: 

 

                     L[R[x]]  =  L[x],  R[L[x]] =   R[x];                  (1) 

3   EXACT COVER PROBLEM                                                    3 
相信有写过双向链表经验的人对这两句话一定不会陌生. 
2.3    双向链表的恢复 
     在双向链表中删除一个结点只要用(1) 就可以了,然后来看下面这一段 
代码: 
                        L[R[x]] =   x, R[L[x]]  =  x;                     (2) 
这段代码会将已经删除掉的结点,重新添加回双向链表中。第一次看到这段 
代码的你是不是会感觉非常奇妙?你有可能会说在链表中进行删除操作但 
是不释放内存的话是不好的编程习惯,会造成内存溢出错误。但是在这里, 
我们要的就是这样的效果。 
     我们在链表中删除,只是进行一个标记,并不进行真正的清空内存操 
作。这样我们后来便可以用(2) 进行恢复操作了。 
     你也有可能会说这段代码会有什么用?下面就让我们来真正看看(2) 强 
大的威力。(2)才是Dancing Links  的核心. 
                  3    Exact  Cover Problem 
3.1    Description 
     上节所说的双向链表的恢复操作会在本节中有重要的作用。下面先让 
我们来看一个问题(Exact Cover Problem)。 
     给定一个01矩阵, 现在要选择一些行,使得每一列有且仅有一个1.  例子 
如下: 
                          0   0  1   0  1  1   0  
                          1   0  0   1  0  0   1 
                          0   1  1   0  0  1   0                   (3) 
                          1   0  0   1  0  0   0 
                          0   1  0   0  0  0   1  
                          0   0  0   1  1  0   1  
对于如上所示的矩阵(3),我们取行集合{1, 4, 5} 便可使每一列有且仅有一 
个1。 
3.2    Solving  an  exact  cover problem 
     很明显,exact cover problem 是一个无法用多项式算法解决的问题,解 
决方法只有搜索!  且看如下搜索代码: 

 

 

3  EXACT COVER PROBLEM                                                   4 

 

if  (A is  empty)  { //A  is  the 0-1  matrix. 

 

     the problem   is solved; 

 

     return  ; 

 

} 

 

choose  a  column,  c, 

 

     that  is unremoved   and  has fewest   elements.;      ...(1) 

 

remove  c  and each  row  i that  A[i][c]   == 1  from  matrix  A;     ...(2) 

 

for  (all  row,  r, that  A[r][c]  ==  1)  { 

 

     include  r  in the  partial  solution.; 

 

     for each  j  that  A[r][j]  ==  1 { 

 

         remove   column  j and  each  row  i 

 

              that  A[i][j]   == 1 from  matrix   A. ...(3) 

 

     } 

 

     repeat  this  algorithm   recursively   on the  reduced   matrix  A. 

 

     resume  all  column  j and  row  i that  was  just  removed;  ...(4) 

 

} 

 

resume  c  and i  we removed   at step  (2)    ...(5); 

 

上述代码是一个普通的搜索过程,如果你觉得比较陌生,可能是因为跟你平 

 

时所用的搜索方法有些不同,但本质上必定是相同的。 

 

                                                                       1 

     我们要做的,是去优化这段代码,但这段代码的算法框架已经固定 , 

 

几乎没有可优化的余地,就算用非递归来优化也不会得到多少的效率提升, 

 

反而会使编码复杂度和出错率大大增加。 

 

     如何去实现代码行(1) (2) (3) (4) 是优化的关键,也是Dancing Links发 

 

挥其作用的地方。我们可以直观的去想到一个简单的方法: 

 

 Step (1):  把矩阵进行扫描,选出未做删除标记的列中元素个数最少的。如 

 

     果你不理解为什么选最少的,可以当它是随便选取的,不影响正确性。 

 

 Step (2):  对当前列和行做标记,标记其已经删除。 

 

 Step (3): 同Step (2) 

 

 Step (4):  把相应的标记删除。 

 

 Step (5): 同Step (4) 

 

   1Step  (1)中有一个巨大的优化,就是选取最少元素的列,但这是搜索优化问题,与我们讨论的重 

 

点Dancing  Links没多大关系,固不做过多论述 

3   EXACT COVER PROBLEM                                                    5 
然而,这个方法很明显是非常低效的,做标记是快速的。但是相应的带来 
的问题,是查找的时候会变得非常慢。复杂度始终是O(n)(n为矩阵大小)。 
在step (1) (2) (3) (4) (5)  中我们都用到了查找操作,所以我们不能忽视查 
找的复杂度。在这个实现方式中,把查找的效率提升多少,整个程序便可提 
升多少。 
     我们再做观察,还可发现,矩阵随着递归的深入便会变得越来越稀疏。 
而我们所对应的查找操作,却没有利用这一特性,一直在盲目的进行查找。 
     或许有读者会自然而然的想到链表。链表可以高效的支持删除操作,链 
表的长度也是随着删除操作的执行而变短,不会存的上述做法的问题。 
     从前面的论述,我们知道了程序的瓶颈在于查找操作。因为矩阵会越来 
越稀疏,所以我们可以直观的感觉到把链表用在此处,会及大的提高效率。 
     有了链表,我们的查找操作只用到了遍历链表,因为已经被标记删除的 
结点是不存在在链表中的。很显然用链表的话查找操作的效率已经提升到 
了极致,不可能再提升了。 
     有人可能会发现问题,我们在链表中删除结点是容易,可是恢复容易 
吗?Step (4) (5) 该如何实现呢?哈哈,请看本论文开头对双向链表的介绍, 
看似无用的双向链表的恢复操作,在这里不是正好用上吗? 
     好了,到这里,已经把Dancing Links基本介绍完了。如果你真正理解了, 
可能会惊叹,这么简单呀!这就是Dancing  Links吗?但是Dancing  Links的 
强大之处还得等到自己实践之后才能体会到。下面我们来细细展开Dancing 
Links。 
3.3    The  Dance  Steps 
     一个比较好的实现方式是用数组来模拟链表,这样也可方便的建立矩 
阵,也可以加快运行速度。对每一个对象,记录如下几个信息: 
   *  L[x], R[x], U[x], D[x], C[x]; 
   *  双向十字链表用LRUD来记录,LR来记录左右方向的双向链表,UD来 
      记录上下方向的双向链表。 
   *  head 指向总的头指针,head通过LR来贯穿的列指针头。 
   *  每一列都有列指针头。C[x]是指向其列指针头的地址。行指针头可有可 
      无,在我的实现中没有显示的表示出来。在某些题目中,加个行指针头还 
      是很有必要的。 
   *  另外,开两个数组S[x], O[x];  S[x]记录列链表中结点的总数。O[x]用来 
      记录搜索结果。 
3   EXACT COVER PROBLEM                                                      6 
                             图1:  矩阵A的表示 
0-1矩阵(3)的存储图形如图(1)所示。 
   *  h代表总的头链表head. 
   *  ABCDEFG为列的指针头。 
     Exact Cover Problem的完整c代码如下所示,调用过程为dfs(0)。 
void  remove(const     int  &c)  { 
//remove   column   c  and  all  row  i that  A[i][c]   ==  1 
     L[R[c]]   =  L[c]; 
     R[L[c]]   = R[c]; 
     //remove   column   c; 
     for  (int  i  = D[c];   i !=  c;  i =  D[i])  { 
     //remove   i  that  A[i][c]   ==  1 
          for  (int  j  = R[i];   j !=  i;  j =  R[j])  { 
               U[D[j]]   = U[j]; 
               D[U[j]]   = D[j]; 
               --S[C[j]]; 
               //decrease    the  count  of  column   C[j]; 
3   EXACT COVER PROBLEM                                                   7 
          } 
     } 
} 
void  resume(const    int &c)  { 
     for  (int  i = U[c];   i !=  c; i  = U[i])  { 
          for (int  j  = L[i];  j  != i;  j =  L[j])  { 
              ++S[C[j]]; 
              U[D[j]]   = j; 
              D[U[j]]   = j; 
          } 
     } 
     L[R[c]]  =  c; 
     R[L[c]]  =  c; 
} 
bool  dfs(const   int  &k)  { 
     if  (R[head]  ==  head)  { 
          One of  the  answers  has  been  found. 
          return  true; 
     } 
     int  s(maxint),   c; 
     for  (int  t = R[head];   t  != head;  t  = R[t])  { 
     //select   the column   c which  has  the  fewest  number   of element. 
          if (S[t]   < s)  { 
               s = S[t]; 
               c = t; 
          } 
     } 
     remove(c); 
     for  (int  i = D[c];   i !=  c; i  = D[i])  { 
          O[k]  = i;//record   the  answer. 
          for (int  j  = R[i];  j  != i;  j =  R[j])  { 
              remove(C[j]); 
          } 
          if (dfs(k   + 1))  { 
4   SUDOKU TO EXACT COVER PROBLEM                                          8 
               return  true; 
          } 
          for  (int  j =  L[i];  j  != i;  j =  L[j])  { 
               resume(C[j]); 
          } 
     } 
     resume(c); 
     return  false; 
} 
函数remove删除了矩阵中的列c及其对应的行。而函数resume则是还原它们, 
可能有些读者会注意到这两个函数里面顺序的问题。在这里我遵循的原则 
是先删除的后还原,后删除的先还原。当然,改变其中的某些顺序是不影响 
正确性的。这样写是为了遵循一定的原则。 
     另外还有一个小问题是我觉得应该提及的。在dfs过程中我们如何选 
择column  c,是一个非常重要的问题。这个程序中我们选择的是元素最少 
的c,这个优化是显然的。 
     但如果是平局,我们该选择哪一个呢?在这个程序中,这一点并没有体 
现出来,如果是平局的话,那这段程序相当于随便选取了一列。这个问题在 
平时应该用可能会极大的影响效率。只能根据具体题目具体来判定如何解 
决了。做题的时候如果你发现你写的Dancing  Links比别人的慢一些,那很 
有可能就是因为这里的问题了。 
3.4    Hust  Online Judge Problem 1017 
     http://acm.hust.edu.cn/thanks/problem.php?id=1017 
     这是一道exact cover problem的一个题目。想测试代码正确性的话可以 
在此提交测试。 
          4    Sudoku to exact cover problem 
4.1    What  is  Sudoku? 
     Sudoku是一个最近几年非常流行的益智游戏。它的中文名是数独。 
     Sudoku问题是在一个9 * 9的格子上,内部有3 * 3的9个小块。你的目标 
是把每一个小格填上1-9中的某一个数,使得每一行、每一列、每一个小块都 
4   SUDOKU TO EXACT COVER PROBLEM                                          9 
包含1-9每个数各一次。在初始情况下,有一些小格是已经填好了的,你所要 
做的是把剩下的填好。 
     Sudoku的规则非常简单,但是却很有挑战性。 
     当今众多手机中已经预装了Sudoku游戏。很多linux桌面系统,比 
如Gnome,也预装了Sudoku。在网上也有很多Sudoku的网站,可以在网 
上搜索”Sudoku”来找到一些。今年的ICPC final总决赛的时候,每天的新闻 
纸背面也是一道数独题。答案在第二天的新闻纸中给出。 
4.2    How to  Solve Sudoku  Puzzle? 
     Sudoku的解法很多,大体上是分为: 
   *  搜索 
   *  构造 
   *  搜索+构造 
     对于普通的9 * 9的Sudoku,最简单的搜索过程是肯定会超时的。我们 
需要加优化,搜索中比较常用的,优化搜索顺序。在这里可以起到非常关键 
的作用。 
下面介绍一种搜索策略: 
     每次判断81个小格的可能性,从中选出可能性最少的来搜索。通 
过位运算等种种优化常数的方法。还是可以达到一个比较理想的效果 
的。pku3074可以在600ms左右用这种方法ac。 
     我们在这个策略的基础上增加一种搜索方式: 
     判断某个数在某个区域内的可能性。 
     加上这两个搜索方式后,Sudoku就可以比较快的出解了。对于9  * 
9的Sudoku几乎是瞬出。pku3074可以做到200ms以内。(常数优化的比较 
好)。 
     对于Sudoku也的构造过程,这里不作过多介绍。Sudoku的构造方法非 
常多,但大多是人工构造的方法。用计算机去构造,是一个非常繁重的过程, 
根本不适合于OI和ICPC。 
     对于在搜索过程中加上部分构造过程增加效率。这里也不作过多介绍。 
方法也是很多,有兴趣的可以去网上查看相关论文。 
     据说今年MCM (美国数学建模竞赛)的B类题目就是Sudoku问题。听我 
们集训队的yyt说,他们便是写了一个构造Sudoku的程序得了一等奖,不过 
程序实在是太长了,1k行+? 
4   SUDOKU TO EXACT COVER PROBLEM                                         10 
4.3    Dancing  Links在解决Sudoku这类问题上的优势 
     很多这种覆盖性的搜索问题都可以转化为exact cover problem。然后我 
们便可以用Dancing Links来解决之。这也是Dancing Links强大的地方。如 
果你认为Dancing Links只是解决一些特殊问题的特殊方法,那你就大错特 
错了。非常多问题可以转化成exact cover problem或类似于exact cover  的问 
题。 
     Dancing Links有什么优势呢? 
   *  Dancing  Links是一种通用的搜索方法,不用你自己去实现搜索过程。 
      不用你对每一道题目都设计数据结构,来设计搜索方法。你所要做的 
      只是去建一个模型。 
   *  Dancing Links不用你自己去想优化搜索的方法。你在建模的和转化的 
      过程中,Dancing Links往往已经为你想好了你都想不到的优化。 
   *  Dancing Links可以减小常数,甚至可以在复杂度上去除一个系数。极 
      大的提高了运行效率。 
   *  Dancing Links代码非常短,方便在比赛现场敲,极大的提高了代码速 
      度。也减少了debug的时间。 
搜索问题千变万化,剪枝非常难想,就算想到了,也很难知道这是不是有用 
的剪枝。在用Dancing  Links来解决这类问题的时候,你会发现这一类的很 
多问题都可以转化成你以前熟悉或做过的题目。那剪枝就不再是问题了。因 
为你已经把剪枝提交想好了。 
     实现也不再是问题了,只要转化正确,再加上Dancing Links的模版。代 
码正确性和实现速度都有了质的提升。做搜索题就仿佛做网络流题目一样 
了。 
     建模+ 模版== AC 
     哈哈,是不是很让人心动。那就来看一下如何转化sudoku吧。 
4.4    转化模型 
     对于一个9 * 9的数独,建立如下的矩阵。: 
     行: 
     一共9 * 9 * 9 == 729行。一共9 * 9小格,每一格有9种可能性(1 - 9), 
每一种可能都对应着一行。 
     列: 
5   EXACT COVER PROBLEM 变种                                                  11 
     一共(9 + 9 + 9) * 9 + 81 == 324 种前面三个9分别代表着9行9列和9小 
块。乘以9的意思是9种可能,因为每种可能只可以选择一个。81代表着81个 
小格,限制着每一个小格只可以放一个地方。 
     这样我们把矩阵建立起来,把行和列对应起来之后,行i可以放在列j上 
就把A[i][j]设为1否则设为0。然后套用Exact Cover Problem的定义:选择一 
些行,使得每一列有且仅有一个1。哈哈,是不是对应着sudoku的一个解? 
     前面我已经说过Sudoku的搜索模型,现在再结合转化后的模型,你会不 
会觉得本质上是一样的呢?其实是一样的。 
     请注意每一列只能有一个1,而且必需有一个1。 
     我们把列分成两类的话,一类是代表着每一个小格的可能性,另一类是 
代表着每个区域的某个数的可能性。第一类是式子中的81,第二类是(9 + 9 
+ 9) * 9这一部分。 
     这样我们所选择的行就对应着答案,而且因为列的限制,这个答案也是 
符合Sudoku的要求的。 
     那你也有可能会说,Dancing Links的优化体现在哪里呢?试想,这个矩 
阵是非常大的(324 * 729),如果不用Dancing Links来解,可能出解吗? 
4.5    Pku  Online  Judge Problem 3076  3074 
     http://acm.pku.edu.cn/JudgeOnline/problem?id=3074 
     http://acm.pku.edu.cn/JudgeOnline/problem?id=3076 
     3074是一个9 * 9的数独。 
     3076是一个16 * 16的数独。 
     这两道题目用前文论述的方法来解,效率非常高。Problem Status里面 
前几名的AC Code基本都是用Dancing Links来解的。(不信你发mail问问他 
们咯). 
     3076里面有些人是0ms AC的。而且代码长度非常短,我十分怀疑他们 
是直接交的数据。也希望POJ的管理员能够把数据变一下吧。 
               5     Exact cover problem  变种 
5.1    Abstract 
     了解本节需要知道A*的一些知识。如果你没有做过有关A*的题目,可 
能在看本节的时候有些困难。因为篇幅,时间和精力都不允许我再去介 
绍A*。所以我下面所介绍的知识就默认你已经很精通A*啦,不会的集训队 
5   EXACT COVER PROBLEM 变种                                                 12 
队员自己去找资料吧。但是我推荐在你对A*有所了解之后,再回过头来看 
一下lrj的书对A*在竞赛中应用的介绍。 
     推荐学习A*所要做的题目: 
   *  第k短路 
   *  15数码 
   *  第k短简单路。 
5.2    Description 
     我们把exact cover problem的定义改一下:在0-1矩阵中选取最少的行, 
使得每一列最少有一个1。 
     我们可以想成一种二分图的支配集的模型: 
左边的点可以支配右边的点,然后我们要选最少的左边的点,使得右边的点 
都被支配了。 
     我们用A* + Dancing Links来解决此题。 
     A*是算法的框架,Dancing Links来实现数据结构,和优化常数。 
     A*中比较重要的是h函数的设计,h函数最好设计成离线的,因为计 
算h函数的复杂度也在很大程度上决定了程序的效率。那h函数如果想不出 
离线的呢?那我们就应该在保证h函数尽量单调的情况下,来减少计算h函数 
的常数。 
     因为h函数是与矩阵有关系的,所以对于稀疏的矩阵来说,选择Dancing 
Links是非常有必要的。随着递归的深入,Dancing Links的优势会体现的越 
来越明显。 
5.3    H  function 
     对于上节所描述的模型,我设计的h函数是这样的: 
     ans来记录h函数的数值。 
     对当前矩阵来说,选择一个未被控制的列,很明显该列最少需要1个行 
来控制,所以我把ans++。该列被控制后,我把它所对应的行,全部设为已 
经选择,并把这些行对应的列也设为被控制。继续选择未被控制的列,直到 
没有这样的列。 
     通过这样的操作,就可以求出一个粗略的h函数。 
5   EXACT COVER PROBLEM 变种                                                  13 
 5.4   Method 
     有了h函数,剩下的就好说了。不管用A*也好,用IDA*也好,实现是比 
较简单的。 
     我的实现方法是IDA*,因为对于一个矩阵进行判重和hash还是比较麻 
烦的。再加上本题答案都比较小。所以IDA*是一个比较好的选择。 
 5.5   Pku  Online Judge  Problem  1084 
     http://acm.pku.edu.cn/JudgeOnline/problem?id=3076f 
     这道题目也是lrj书上一道习题。题目模型就是我上面所说的。 
     我写的程序实验可以过6 0这样的数据。推荐写个程序来实践一下。 
关于SVPWM七段式五段式调制后的相电压和线电压波形——大疆DJI技术笔试 1.SVPWM七段式/五段式调制的相电压和线电压波形 脉宽调制(PWM)在并网变流技术中得到了广泛的应用。与正弦脉宽调制(SPWM)的控制方法相比,SVPWM方法具有直流侧电压利用率高,电压谐波小,易于数字化实现等显著的优点,从而使SVPWM在实际的应用中越来越普遍。TMS320F28335是32位浮点的DSP控制器,具有150MHz的高速处理能力,18路PWM输出,与前几代数字信号控制器相比,性能平均提高了50%。其中具体的SVPWM理论实现的原理,请参考我的博客永磁同步电机的矢量控制策略(七)一一一SV 阅读详情

相关推荐

阿里云大模型 ACP 认证教材内容突变?这些改动藏着通关密码,不看亏大!

【摘要】核心章节大换血,安全合规融入实战场景,大模型微调用数学深度解析,部署章节带来阿里云产品对比实战攻略,甚至整章内容被替换成藏满学习彩蛋的行业趋势指南。这些改动不仅重塑考试重点,更暗藏官方命题风向——安全合规考场景方案,微调原理考几何解析,部署设计考分析框架。无论你是数学小白还是部署新手,这篇攻略都将带你吃透变动逻辑,附赠急救包和考点清单,帮你抓住这些“隐形加分项”,速来解锁通关秘籍!

davidkorhenn的博客 1755

【转】DLX 精确覆盖 重复覆盖

问题描述: 给定一个n*m的矩阵,有些位置为1,有些位置为0。如果G[i][j]==1则说明i行可以覆盖j列。 Problem: 1)选定最少的行,使得每列有且仅有一个1. 2)选定最少的行,使得每列至少一个1. DLX原理: 这类属于NP问题的问题,可以使用搜索解决。但是普通的搜索必超时无疑。因此我们要设法加优化来加快速度。 Dancing Links从数据结构方面对此类搜索进...

weixin_30897233的博客 282

LVGL与STM32的理解(基于正点原子资料)

我们要在lcd_draw_fast_rgb_color里面实现对屏的具体操作(也就是在这里实现自己的代码)。lcd_set_window、lcd_write_ram_prepare、lcd_wr_data这三个函数是本例程LCD屏的控制函数(也就是自己写的函数)。以下是stm32工程的文件目录,GUI_APP也可以忽略(细节参考正点原子例程):这里主要是再次加强一下印象,主要就是把。,里面的lcd_init()与lcd_display_dir是。它们都是LVGL的接口,按照它们的需求,把内容给它们即可。

weixin_39257775的博客 3435

Dancing Link 详解(转载)

Dancing Link详解: http://www.cnblogs.com/grenet/p/3145800.html Dancing Link求解数独: http://www.cnblogs.com/grenet/p/3163550.html 对于求解9*9的数独,貌似Dancing Linking算法并不怎么理想,还没暴搜来得快,但是16*16的数独优化就明显了。 DLX求解问题过...

weixin_34198583的博客 246

IMU预积分【SLAM】

预积分的推导过程比较多,所以这里只记录关键结论。 其实这些公式不太好记忆,因为预积分推导过程的想法来源很巧妙,无法看出物理意义。一切推导的来源: 最好记忆的旋转相对运动量: △Rij≐RiTRj=∏k=ij−1Exp((ω~k−bg,k−ηgd,k)△t)\triangle R_{ij} \doteq R_{i}^{T}R_{j} = \prod_{k=i}^{j-1}Exp((\tilde{\omega}_{k}-b_{g,k}-\eta_{gd,k})\triangle t) △Rij​≐RiT​Rj​

Tong_1024_的博客 1368

景观格局指数计算方法及代表的生态学意义(待补充)

景观指数 斑块密度(PD) 斑块密度(PD)表现某种斑块在景观中的密度,可反映出景观整体的异质性与破碎度[17],公式为PD=NP/A(1)式中NP———斑块数量,个A———景观或斑块的总面积,hm2PD———斑块密度,个/hm2 最大斑块指数(LPI) 最大斑块指数(LPI)用于确定景观中的优势斑块类型,间接反映人类活动干扰的方向和大小,公式为LPI=amaxA×100%(0≤LPI≤100%)(2)式中amax———景观或某一种斑块类型中最大斑块的面积,hm2LPI———最大斑块指数,% 凝聚

soderayer的博客 13万+

Dancing Links ---- D - Sudoku

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . . . 6 7 3 5 . . . . . . . 2 9 3 . 5 6 9 2 . 8 . . . . . . . . . . . 6 ...

qq_36386435的博客 427

SAP-FICO LSMW实战:批量导入财务凭证与固定资产主数据(AS91)的完整指南

本文详细介绍了SAP-FICO中LSMW工具在批量导入财务凭证与固定资产主数据(AS91)的完整流程与实战技巧。从基础概念、环境准备到财务凭证导入全流程,特别针对AS91历史资产导入的日期逻辑和关键字段映射提供了专项指南,并分享了常见错误排查与性能优化建议,帮助用户高效完成SAP数据迁移任务。

weixin_29230649的博客 503

Claude Code实战:从环境部署到Vibe Coding与MCP扩展全解析

AI辅助编程正在从对话式问答走向上下文感知的终端协作。真正的变化在于,模型不再只是输出代码片段,而是能直接读取项目文件、执行命令、运行测试,形成闭环反馈。这种能力让开发者从逐字符实现转变为方向制定与质量验收,Vibe Coding工作流由此成为新常态。与此同时,MCP扩展协议统一了模型与外部工具的连接方式,使AI助手从编程工具进化为可调度浏览器、数据库、设计稿等多元服务的中心节点。但能力越强,越需要边界控制:环境部署时的权限隔离、提示词中的上下文编排、以及严格的代码审查与日志记录,都是工程落地的关键。本文以

weixin_34268843的博客 581

PCL基础:getTransformation函数全流程解析与应用实例,一篇文章精通点云变换

在 Eigen 和 PCL 中,getTransformation是一个常用的函数,用于根据输入的平移和旋转信息(如欧拉角或四元数)生成一个仿射变换矩阵(Eigen::Affine3f或 Eigen::Affine3d)。1)在 Eigen 中,可以通过四元数和平移向量构造一个变换矩阵。2)讲解了从四元数转换到欧拉角,或者从欧拉角转换到四元数的方法。

weixin_42896234的博客 1368

基于YOLOv11的无人机目标检测系统:实现drone、bird、aircraft多类别识别

采用改进的YOLOv11网络结构,平衡检测精度和速度融合VisDrone和UAVDT数据集,增强模型泛化能力设计多尺度特征融合模块,提升小目标检测性能开发直观的UI界面,便于实际部署和应用。

YOLO 322

dancing link X算法(DLX算法)详解

我觉得这个博客讲的很不错,就转载过来啦。 理解DLX算法的含义这个很不错,但是拿来做算法竞赛题,我还是觉得kuangbin大佬的板子(静态链表)比较好用。 转载自:https://philoscience.iteye.com/blog/1537004 Exact-Cover问题: 问题描述:给定一个0/1矩阵(一般是稀疏矩阵),选出一些行,使得由这些行构成的新矩阵中每一列有且仅有一个1。换个说法,...

int_Brosea的博客 1776

SCSA,scCATCH,SciBet,SingleR 四种注释方法比较

以下是和四种细胞类型注释方法的详细对比,从。

qq_40256654的博客 1213

Dancing Links hdoj 5046 3656 2295

先做的hdoj 5046,记得以前做过一个类似的dp,但是那个是求所有城市到机场的距离和的最短长度,而且是一维的,所以就没多想敲了一发dp,结果当然就是wa了。。。 后来看kuangbin大爷的题解才知道原来是DLX模板题。。 然后发现这篇文章写的不错转载一下:http://www.cnblogs.com/grenet/p/3145800.html 来一发kuangbin大爷的标程作模板:h

AngelBeats! 477

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【TJOI2014】拼图(puzzle) dancing links X

描述小 Z 最近迷上了拼图游戏,然而智商有限,他总是无法拼出完整图案。游戏是这样的:首先小 Z 会得到一些拼图碎片,然后他试着重新排列这些碎片使得它们组成一个大小为 4 ∗ 4 的正方形。如下图。注意小 Z 不能旋转或者翻转这些碎片。 Image Lost 小 Z 得到如图 1 的碎片,然后经过重新排列得到图 2 的正方形。 由于小 Z 实在太笨了,聪明的你请写一个程序帮助他来解决这个问题吧。

老臣 870

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

hust1017 Exact cover dancing links 美丽的舞蹈

Exact cover 刚看了DLX,找到hust1017练了一下 为什么叫dancing links呢,据说是因为算法的创造者knuth感觉这个算法太妙了,不尽让人想起美丽的舞蹈,于是就有了这个名字。的确,DLX对搜索的优化让人叹为观止,缩小稀疏图,减小搜索范围,同时能很快的恢复图的构建,非常妙! momodi 的论文《Dancing Links 在搜索中的应用》 还有原著的英文论文...

weixin_30242907的博客 120

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【数据结构】基于比较的排序算法 - 交换排序

本文介绍交换排序中的冒泡排序与快速排序。冒泡排序通过相邻元素比较交换,实现升序,时间复杂度最坏为O(N²),空间复杂度O(1),稳定且适合小规模有序数据。快速排序采用分治思想,以基准值划分区间,平均时间复杂度O(N log N),空间复杂度O(log N),但不稳定,实际应用中性能优异,可通过随机基准、小区间优化等提升效率。

careathers的博客 316

pandas 深度入门:从数据结构到一份真实销售报表

本文系统讲解Pandas核心应用,从三分钟安装到完整月度报表生成,涵盖数据读取、清洗、筛选、分组聚合、表连接、透视表与时间序列等13个关键环节。强调“先看数据再动手”,掌握Series/DataFrame/Index结构本质,熟练运用loc/iloc、merge校验、agg/transform区别,通过真实案例实现高效报表自动化,告别手动Excel操作。最后提供性能优化与高频报错解决方案,助力读者快速上手,真正实现“写二十行代码,跑三秒出结果”。

信息安全领域优质创作者|操作系统领域专家 241

工单系统的数据结构化:故障分类体系设计与报表可用性

很多团队上完工单系统半年,会发现一个尴尬的事实:单子照常在走,报表却始终出不来。导出的 Excel 几千行,看不出趋势、算不出口径、答不了"哪类故障占大头"。问题几乎都不在系统,而在数据模型的第一层——。这篇文章把这件事拆开讲:自由文本为什么会失效、分类体系怎么分层、表怎么建、老数据怎么迁、上线前怎么验收。

ITyunwei0987的博客 268

【Linux进程(二)】深入 Linux 内核:进程状态切换与底层数据结构的秘密

本文从操作系统理论与Linux内核源码双重视角,深入解析进程状态的底层机制。通过“侵入式链表”与“偏移量计算”揭示task_struct如何同时存在于多类数据结构中,实现高效调度与管理。结合ps命令与实战代码,详解R、S、T、Z、X等状态的成因与行为,涵盖前后台切换、暂停/恢复、僵尸进程、孤儿进程等典型场景,揭示进程生命周期的完整图景,实现“知其然更知其所以然”。

wacsii的博客 291

数据结构:9.Map和Set

有的讲解会说这里key是标识作用,这种说法其实没有太大意义,就算知道了他是标识value的作用又如何,在实际的使用过程中,我们只会根据具体的效果选择使用的方法等,不会执着于“标识”这种说法。2.由于哈希函数的设计原则太过理论,它仅仅是在认为:这些通过关键码算出来的index不同 的情况下设计的,然而这种理论化的设计原则在遇到冲突时,恰恰就出现了问题,而我们能做的,就是降低冲突率。虽然哈希表的使用过程中存在冲突,但是在实际的使用过程中,哈希表的冲突率是不高的,冲突的个数是可控的。

2602_95646088的博客 184

[C++高阶数据结构·图论下] 最短路径:为什么“挑最小的”一定正确?

本文系统对比最小生成树与最短路径的核心差异,聚焦三类最短路算法:Dijkstra(非负权、贪心确认)、Bellman-Ford(可负权、反复松弛)、Floyd(全源、分层中转)。核心区别在于:MST 关注“连通所有点”的最小代价(边数固定),而最短路关注“两点间路径最短”(边数可变)。关键反直觉点是:负权对 MST 无害,却使 Dijkstra 失效——因“绕远更近”破坏贪心前提。算法本质反映三种处理不确定性的策略:确认式(Dijkstra)、迭代修正(Bellman-Ford)、分层逼近(Floyd)。强

Tairitsu_青云 501

[C++高阶数据结构·图论上] 最小生成树:为什么“选边”和“选点”是两条路?

本文系统讲解最小生成树(MST)的核心思想与两大算法:Kruskal与Prim。强调MST目标是用最小权值总和连接所有顶点形成一棵树,而非单边最小。通过三条构造准则(用图中边、恰n-1条边、无环)统一框架。Kruskal按边贪心,依赖并查集判环,适合稀疏图;Prim按点扩张,利用割集特性天然避免成环,需起点,适合稠密图。两算法本质差异在于“判环”机制与数据结构选择,且与最短路径问题在连通性、负权处理上截然相反,需分篇厘清。

Tairitsu_青云 213

Vue3 低代码移动表单设计器实战(二):缩放画布下的拖拽系统与树状级联数据结构

本文深入剖析Vue3低代码表单设计器在缩放画布下的拖拽失效问题,揭示SortableJS在CSS Transform下坐标崩溃的数学根源。通过自研独立视觉克隆壳层与逆向几何补偿算法,实现精准拖拽;采用扁平数据存储+运行时树状计算结构,解决级联依赖与深克隆难题,确保逻辑一致性与性能优化,为复杂低代码系统提供可复用的工程范式。

NanChen的博客 331

排序算法深度笔记(上):比较类排序的思想演进与代码实现

与。本文聚焦前者 —— 也就是通过元素间两两比较来确定相对顺序的排序算法,从最朴素的 O (n²) 基础排序,到工业级主流的 O (nlogn) 进阶排序,逐层拆解设计思想、带注释的代码实现与边界细节。当我们理解了比较排序的性能边界,也就自然引出了非比较排序的存在意义。所有代码均遵循统一的实现规范:入口函数前置空数组与单元素边界校验,基于数组原地修改,主函数附带可直接运行的测试用例,与练习代码风格完全对齐。

2401_87069538的博客 592

【数据结构】静态 & 动态顺序表

顺序存储来实现线性表:链式存储实现线性表:存放在一段,数据元素之间的逻辑关系由物理存储关系体现:存储在,数据元素之间的逻辑关系用来表示:且大小固定()的数组:可以自动调节大小()的数组。

2301_80694580的博客 183
上一篇: 轮回 ---- 写给龙葵
下一篇: [NOIP2008]火柴棒等式
code_beauty
博客等级 码龄16年 25粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值