穷举搜索

对于一些困难的问题,我们只能穷举(brut force)搜索,是的,我们知道“穷举搜索”这个词,可是,具体怎么穷举呢?

很多问题可以归结到图的搜索,对于图的搜索,大家应该都知道 DFS 和 BFS,然而可能没有多少人知道如何对图做穷举搜索。我先举一个最简单的例子:哈米尔顿环(hamilton cycle),不知道的,可以去维基百科上去查。

#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <vector> #include <algorithm> using namespace std; int start = 0; int N; vector<vector<int> > G; vector<int> P; // current path/stack vector<int> D; // vertex depth in stack, -1 indicate not yet discovered // so D also serve as Mark array of DFS void printham() { printf("found hamilton cycle: "); for (int i = 0; i < N; ++i) printf("%d ", P[i]); printf("\n"); } void hamilton(int x, int k) { if (k == N) { assert(0); // never goes here } else { D[x] = k; // mark x P[k] = x; // put x into the path for (int j = 0, c = G[x].size(); j < c; ++j) { int y = G[x][j]; // Edge(x to y) if (D[y] != -1) { // found a cycle // (1 + k - D[y]) is the cycle length // so the condition is also (D[y] == 0 && k == N-1) if (y == start && k == N-1) printham(); // this is a hamilton cycle } else // not yet discovered hamilton(y, k+1); } D[x] = -1; // un-mark } } int main(int argc, char* argv[]) { int lineno = 1; while (!feof(stdin)) { int x, y; int fields = scanf("%d %d\n", &x, &y); if (fields == 2) { if (min(x, y) < 0) { fprintf(stderr, "invalid vertex number at line %d\n", lineno); return 3; } if (G.size() < (size_t)max(x, y) + 1) G.resize(max(x, y) + 1); G[x].push_back(y); } else { fprintf(stderr, "bad record at line %d\n", lineno); return 3; } lineno++; } N = G.size(); P.resize(N); D.resize(N, -1); if (argc >= 2) start = atoi(argv[1]); else start = 0; hamilton(start, 0); return 0; } 为了突出递归的逻辑,这个程序把所有(每次递归都相同的)函数参数换成了全局变量,从软件工程角度讲这是有问题的,但是作为示例,逻辑上更清楚一些。

这个程序从 stdin 读取一个图,这个图共 N 个结点,结点编号是 0~N-1。每行是一条边 src dest,中间用空白分隔。

从代码效率上讲,这个程序也也不够高效,一个在数据结构上(how to optimize vector<vector<int> > G ?)和程序逻辑(非递归) 上充分优化的版本,大约比这个要快10倍。

这个程序也接受一个参数 start ,表示搜索的起始结点,start 的默认值是 0。

下面是一个图的示例(g1.txt):

0 1
1 2
3 5
2 4
5 1
0 2
2 3
3 4
5 0
4 5

运行 hamilton 3 < g1.txt

输出结果是:found hamilton cycle:3 4 5 0 1 2

穷举的一般代码框架是:

bruteforce(x, depth) { if (depth == max_depth) { // .... else { mark[x] = true; for (y : x.children) { if (mark[x]) // ... else bruteforce(y, depth+1); } mark[x] = false; // this is the only diff with DFS } }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值