感悟DFS
昨天看到了一句话让我对DFS算法有极深的感悟。
这句话就是:DFS有三个条件:1.最深深度 2.结束条件 3.如何扩展。
其实对于1, 2,两点,感觉不是问题的关键,第三点
才是问题的核心。如何说呢?还是来结合一个实例吧,不然,
很难说清楚。
例题:
有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,
最初,A和B桶都是空的,而C桶是装满牛奶的。
有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。
当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。
解题思路:
每次最多无非有6种倒法,即a->b;a->c;b->a;b->c;c->a;c->b。
所以如果用a、b、c代表三个桶的容积,x、y、z代表当前三个桶内的牛奶数,
那么不难算出执行完a->b后,x变为max(0,x+y-b),y变为min(b,x+y),z不变。
其它倒法类似。
说到这里,思路也就出来了。什么时候a->b,什么时候a->c……
这个就是递归的方向的控制了。这个也是相当重要的,因为,
这个是扩展的第一步,如果这一点解决不了,那么就没有后话了。
其实这一点是很好控制的,只要a>0, b不满,就可以实现a->b了。
其它的6个倒法也是一样的。
有了扩展的方向以后,递归就完成50%,另外的一半就是,在每
个方向上的具体的参数变化了,比如本题的x变为max(0, x+y-b),
y变为min(b, x+y), z不变……,有个这两点之后,那么DFS的
核心内容也就完成了,一不小心,你就会AC了。
下面给出核心的代码。
if(a>0 && b<B) //A向B倒, c不变
DFS(max(0, a+b-B), min(B, a+b), c);
if(a>0 && c<C) //A向C倒,b不变
DFS(max(0, a+c-C), b, min(C, a+c));
if(b>0 && a<A) //B向A倒,c不变
DFS(min(A, a+b), max(0, b+a-A), c);
if(b>0 && c<C) //B向C倒,a不变
DFS(a, max(0, b+c-C), min(C, b+c));
if(c>0 && a<A) //C向A倒,b不变
DFS(min(A, a+c), b, max(0, a+c-A));
if(c>0 && b<B) //C向B倒,a不变
DFS(a, min(B, b+c), max(0, b+c-B));
6个if语句就是控制方向的。
DFS中的max, min就是用来控制参数的变化的。
总结一下,其实我一直在强调“如何扩展”这个方面。
这个方面又分为两个细节:
1.扩展方向
2.参数变化
思考一个DFS题目,要着重在这两个细节考虑。
posted on 2011-10-17 09:33 More study needed. 阅读(355) 评论(0) 编辑 收藏 举报