标签:相等 效果 cst 是你 条件 ace 必须 最优 过多
众所周知,搜索是个好东西,他能在很多时候(就是你不会正解打暴力的时候)派上用场。
然而搜索的时间复杂度实在是太高了,大多数都是指数级别的,这让人很是头疼
那么我来总结一下对搜索进行优化的技巧:剪枝
什么是剪枝
我们知道,搜索的进程可以看做遍历一棵搜索树的过程。而所谓的剪枝,就是通过某种判断,避免一些不必要的遍历过程。
形象的来说,就是剪掉搜索树上的一些枝条来达到减少遍历次数,缩短时间复杂度的效果
剪枝的原则
1.正确性
2.准确性
3.高效性
然后就会出现一个矛盾。
我们如果想要尽可能优的剪枝,就必须提高判断的准确性,就是尽可能只要一发现就剪去,这就常常会提高判断的复杂度,同时就降低了剪枝的效率
但是如果剪枝消耗的时间过多,就会降低判断的准确性所带来的优化
所以我们很多时候都要考虑这两者之间的关系,看看如何处理
剪枝的技巧
1.优化搜索顺序
2.排除等效冗余
3.可行性剪枝
4.最优性剪枝
5.记忆化
我们来看一个比较简单的例题
数的划分:传送门
这道题最简单的方法显然就是一位一位的枚举,然后判断是否成立,是否和之前的情况重合。
显然会TLE
但是我们发现这个东西是不考虑顺序的,也就是说我们可以指定一个顺序,然后只要存储下来个数就可以了
不妨将方案从小到大,所以拓展节点时的下界就是前一个节点
上界是什么?
假设我们已经枚举到了第n-1个点,正在枚举第n个点,由于后一个数都是大于等于前一个数的
所以取最极端的情况,就是第n-1个数后面的所有数都相等,这时求平均数,显然就是第n个数的上界,因为它无论如何也不可能突破这个上界的
搜索的代码还是比较好些的
这里再提供另一种做法
#include<cstdio> #include<iostream> #include<cstdlib> #include<iomanip> #include<cmath> #include<cstring> #include<string> #include<algorithm> using namespace std; int n,k,f[201][7]; int main(){ cin>>n>>k; for (int i=1;i<=n;i++) {f[i][1]=1;f[i][0]=1;} for (int j=2;j<=k;j++) {f[1][j]=0;f[0][j]=0;} for (int i=2;i<=n;i++) for (int j=2;j<=k;j++) if (i>j) f[i][j]=f[i-1][j-1]+f[i-j][j]; else f[i][j]=f[i-1][j-1]; cout<<f[n][k]; return 0; }
自己领悟吧
标签:相等 效果 cst 是你 条件 ace 必须 最优 过多
原文地址:https://www.cnblogs.com/lcezych/p/10990200.html