回 帖 发 新 帖 刷新版面

主题:关于 排列&组合——深搜解法

近几天在坛子上见人讨论关于排列和组合的求法,我贴出我的程序,请大家过目

在M$中任选K个字母。

排列:
DECLARE SUB dfs (d!)
CLS
CONST maxn = 100
DIM SHARED a(maxn), used(maxn), l, k, m$

INPUT m$, k
l = LEN(m$)
CALL dfs(1)


SUB dfs (d)
IF d - 1 = k THEN
FOR i = 1 TO k: PRINT MID$(m$, a(i), 1); : NEXT i
PRINT
ELSE FOR i =  1 TO l
       IF used(i) = 0 THEN
         used(i) = 1
         a(d) = i
         dfs (d + 1)
         used(i) = 0
       END IF
     NEXT i
END IF
END SUB


组合:
DECLARE SUB dfs (d!)
CLS
CONST maxn = 100
DIM SHARED a(maxn), used(maxn), l, k, m$

INPUT m$, k
l = LEN(m$)
CALL dfs(1)


SUB dfs (d)
IF d - 1 = k THEN
FOR i = 1 TO k: PRINT MID$(m$, a(i), 1); : NEXT i
PRINT
ELSE FOR i = a(d - 1) + 1 TO l    '细心的人也许已经发现,组合和排列只在这一处改动了1个数
       IF used(i) = 0 THEN
         used(i) = 1
         a(d) = i
         dfs (d + 1)
         used(i) = 0
       END IF
     NEXT i
END IF
END SUB


算法为DFS,深度优先搜索。
欢迎发表意见或建议,新手有不明白也欢迎提问。

回复列表 (共34个回复)

沙发

以上程序是从一道题扩展来的:
输入N、K,输出从1,2,3。。N中选K个数的排列(组合):

DECLARE SUB dfs (d!)
CLS
CONST maxn = 100
DIM SHARED a(maxn), used(maxn), k,n

INPUT n, k
CALL dfs(1)


SUB dfs (d)
IF d - 1 = k THEN
FOR i = 1 TO k: PRINT a(i); : NEXT i
PRINT
ELSE FOR i =  1 TO n         '同样只改这里就可以完成 排列到组合 的转化
       IF used(i) = 0 THEN
         used(i) = 1
         a(d) = i
         dfs (d + 1)
         used(i) = 0
       END IF
     NEXT i
END IF
END SUB


可以看到,几乎完全一样。
这几个程序可以看出非常明显的深搜框架,想学搜索的可以参考。正是为了这个原因我才发这个主题。

板凳

好贴!

3 楼

我写的深搜框架(严重建议新手看看……高手就别看了,没什么意义):

'定义数据结构
const maxn=100
dim shared s(maxn)   's,即stack,即栈,用来存结果的。由此,我对 rickone的“BASIC不能用栈”表示怀疑,并且,有时间我会用QBASIC,用栈把那个表达式求值写出来的。难度并不高。我用TP写了140行左右,用BASIC应该可以尽量控制在120行左右。

'DFS子程序
sub dfs(d)   'd,即depth,即深度。
if 现在的结点是目标结点 then 把S中的数输出,就是1组解了
else for k=1 to r        'k为方案编号,在上题中就是1到n
      if 方案k符合要求 then
         1、设置标记     '上题中就是将used(i)设为1,即已经用过
         2、当前状态入栈记录下来
         3、dfs(d+1)    '递归调用
         4、清除标记     '上题中就是将used(i)重新改成0
      end if
     next k
end if
end sub


总结:深搜不像动态规划那么活,它是有框架的。一般只要确定一个程序可以用深搜,就可以直接套框架。
PS:因为我的深搜是在PASCAL上学的,所以用BASIC描述或许会有些不太清楚,不明白的可以加QQ:155175157,注明是编程

4 楼

深搜是不是深度优先搜索的简称?
我还没学过,其实我系统学的东西很少,我只是喜欢编程,只有高一的时候参加过PASCAL语言班,但是学得很浅,那年的竞赛又取消了,所以很遗憾。我只是不断的编东西,脑子里突然出个点子,然后就编。我编的全是有意思的东西;)

什么是堆栈?FILO,first in last out,它的本质是‘线性表’,实现起来不是很简单数组一下搞定,至于为什么叫堆栈,是在对这个线性表的操作上,程序=数据结构+算法 嘛,如果我对这个线性表只对头部进行插入、删除、读取的操作,这不就是栈?

你的那个深搜是对‘图’的操作吗?图这样‘多对多’的复杂的数据结构都能搞定,栈算什么。

其实我的那个算表达式的程序里也有一个Stack(),你没仔细看?我的方法是先把中缀式转化成后缀式,转化的时候就需要一个栈。至于你说的用双栈算表达式,不知道是不是《数据结构》里栈应用的一个例子?我还是喜欢用后缀式。

5 楼

这才是好程序!
我贴的那个,自己都看不明白!

6 楼

楼上的过奖。

回rickone兄,深搜=depth-first search=深度优先搜索。你那个我是没仔细看的。我并不认为中缀比后缀麻烦,用双堆栈可以很简单解决。tsinghua的绿皮《数据结构》上的确有这样一道题,但我没怎么看。
深搜可以对图,树等很多东东进行遍历,不只图。当然,深搜原本的确是对图的一种遍历方法。
我只是对兄弟你那时说的“那你在BASIC里用栈我看看”表示一下看法而已。现在既然大家都已经能轻易解决那个问题,就不说了吧。

7 楼

可否把你那个表达式求值的程序发来看看
Z_Jumping@163.com

8 楼

先顶起来,有空再细看。不过没有注释很难看懂啊。

9 楼

认真看了吗?我在下面有个深搜框架,你直接套框架不就看懂了?

10 楼

希望将深搜的问题细细讲解一下,要深入浅出,好让我等新手能听懂。
最好多举些例子。

我来回复

您尚未登录,请登录后再回复。点此登录或注册