赞
踩
剪枝,是为了减少搜索树规模,尽早排除搜索树中不必要的分支的一种手段。形象的说,就像是剪掉了搜索树的枝条,故称为“剪枝”。在深度优先搜索中,有以下几类常见的剪枝方式:
在一些搜索问题中,搜索树的各个层次、各个分支之间的顺序不是固定的。不同的搜索顺序会产生不同的搜索树形态,其规模大小也相差甚远。
以下的:
在搜索过程中,如果我们能够判定从搜索树的当前节点上沿着几条不同分支到达子树是等效的,那么,只需对其中的一条分支执行搜索。
在搜索过程中,及时对当前状态进行检查,如果发现分支已经无法到达递归边界,就执行回溯、这就好比我们在道路上行走,远远看到前方是一条死胡同,就应该立即折返绕路,而不是走到路的尽头再返回。
某些题目条件的范围限制是一个区间,此时可行性剪枝也被称为“上下界”剪枝。
在最优化问题的搜索过程中,如果当前花费的代价已经超过了当前搜索到的最优解,那么无论采取多么优秀的策略到达递归边界,都不可能更新答案。此时可以停止对当前分支的搜索,执行回溯。
可以记录每个状态的搜索结果,在重复遍历一个状态时直接检索并返回。这就好比我们对图进行深度优先遍历时,标记一个结点是否被访问过。
输入样例:
5 1996 1 2 1994 12 29输出样例:
2
- #include <cstring>
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- const int N = 20;
-
- int n, m;
- int w[N];
- int sum[N];
- int ans = N;
-
- void dfs(int u, int k)
- {
- // 最优性剪枝
- if(k >= ans) return;
- if(u == n)
- {
- ans = k;
- return ;
- }
-
- for(int i = 0; i < k; i ++ )
- if(sum[i] + w[u] <= m)
- {
- sum[i] += w[u];
- dfs(u + 1, k);
- sum[i] -= w[u];
- }
-
- sum[k] = w[u];
- dfs(u + 1, k + 1);
- sum[k] = 0;
- }
-
- int main()
- {
- cin >> n >> m;
- for(int i = 0; i < n; i ++ ) cin >> w[i];
-
- // 优化搜索顺序
- sort(w, w + n);
- reverse(w, w + n);
-
- dfs(0, 0);
-
- cout << ans << endl;
-
- return 0;
- }
输入样例:
4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4...... ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3. end输出样例:
417369825632158947958724316825437169791586432346912758289643571573291684164875293 416837529982465371735129468571298643293746185864351297647913852359682714128574936
- #include <cstring>
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- const int N = 9, M = 1 << N;
-
- int ones[M], map[M];
- int row[N], col[N], cell[3][3];
- char str[100];
-
- void init()
- {
- for (int i = 0; i < N; i ++ )
- row[i] = col[i] = (1 << N) - 1;
-
- for (int i = 0; i < 3; i ++ )
- for (int j = 0; j < 3; j ++ )
- cell[i][j] = (1 << N) - 1;
- }
-
- void draw(int x, int y, int t, bool is_set)
- {
- if (is_set) str[x * N + y] = '1' + t;
- else str[x * N + y] = '.';
-
- int v = 1 << t;
- if (!is_set) v = -v;
-
- row[x] -= v;
- col[y] -= v;
- cell[x / 3][y / 3] -= v;
- }
-
- int lowbit(int x)
- {
- return x & -x;
- }
-
- int get(int x, int y)
- {
- return row[x] & col[y] & cell[x / 3][y / 3];
- }
-
- bool dfs(int cnt)
- {
- if (!cnt) return true;
-
- int minv = 10;
- int x, y;
- for (int i = 0; i < N; i ++ )
- for (int j = 0; j < N; j ++ )
- if (str[i * N + j] == '.')
- {
- int state = get(i, j);
- if (ones[state] < minv)
- {
- minv = ones[state];
- x = i, y = j;
- }
- }
-
- int state = get(x, y);
- for (int i = state; i; i -= lowbit(i))
- {
- int t = map[lowbit(i)];
- draw(x, y, t, true);
- if (dfs(cnt - 1)) return true;
- draw(x, y, t, false);
- }
-
- return false;
- }
-
- int main()
- {
- for (int i = 0; i < N; i ++ ) map[1 << i] = i;
- for (int i = 0; i < 1 << N; i ++ )
- for (int j = 0; j < N; j ++ )
- ones[i] += i >> j & 1;
- while (cin >> str, str[0] != 'e')
- {
- init();
-
- int cnt = 0;
- for (int i = 0, k = 0; i < N; i ++ )
- for (int j = 0; j < N; j ++, k ++ )
- if (str[k] != '.')
- {
- int t = str[k] - '1';
- draw(i, j, t, true);
- }
- else cnt ++ ;
-
- dfs(cnt);
-
- puts(str);
- }
-
- return 0;
- }
输入样例:
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0输出样例:
6 5
输入样例:
100 2输出样例:
68
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。