搜索的优化

搜索的优化1——剪枝

何谓剪枝?我们可知,搜索是基于搜索树的一个算法,所谓剪枝,就如其字面的意思,剪去一些没有用的枝条。

显然这样可以加快搜索的进程,从而减小时间复杂度。

剪纸的原则:1,正确——不能剪掉含有我们需要的解的枝条,2,准确,3,高效

一些常用的剪纸方法:

1,可行性剪枝(上下界剪枝)

搜索是一种暴力的算法,其思想是有n层,再每层进行枚举等操作,在到达边界条件的时候,判断找到的解是否合法。

通过这个思想我们可以枚举的范围,确定下界和上界,从而达到剪枝的目的。其中确定上界是因为,如果超过枚举上界

往往就不能抵达递归边界了,所以成为可行性剪枝。

例题[NOIP提高组]数的划分

Description

将整数N分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序),问有多少种方案数。

例如 将整数7分成3份,我们认为1 1 5; 1 5 1; 5 1 1是同一种分法。

Input

第一行两个整数N和M

Output

一行代表总的方案数 

首先只考虑单纯搜索的做法,只是有K层,每层枚举一个数满足a1+a2+...+ak=n即可,方案数不得冲突。

因为每一层存在枚举一个数字,所以考虑上下界剪枝,我们可以发现因为要求方案不相同,所以ai<=ai+1

所以我们确定了枚举的下界ai-1,再考虑枚举的上界,因为要求分成k份,要求k份的总和为n,所以假设我们

现在枚举到了第pos个数,前pos-1个数的和为sum,为了既满足ai-1<=ai并且k份的总和能够达到n,所以剩下

每一位的大小不能超过(n-sum)/(k-pos),所以只要满足sum+i*(k-pos)<=n即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define maxn 10
 6 
 7 using namespace std;
 8 
 9 int n,k;
10 int ans;
11 
12 inline void dfs(int pre,int sum,int pos)
13 {
14     if(pos==k)
15     {
16         if(sum==n) ans++;
17         return;
18     }
19     for(register int i=pre;sum+i*(k-pos)<=n;++i)
20         dfs(i,sum+i,pos+1);
21 }
22 
23 int main()
24 {
25     scanf("%d%d",&n,&k);
26     dfs(1,0,0);
27     printf("%d
",ans);
28     return 0;
29 }
P1025

 2,记忆话搜索

所谓记忆话,就是对于所有已经搜到的节点进行记忆话,这样可以避免子问题被重复计算,从而完成剪枝。

例题[SHOI2002]滑雪

Description

Michael喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当

你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道在一个区域中最长的滑坡。区域由一

个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

1   2   3   4   5
16  17  18  19   6
15  24  25  20   7
14  23  22  21   8
13  12  11  10   9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可行的滑坡为

24-17-16-1(从24开始,在1结束)。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。

Input

输入的第一行为表示区域的二维数组的行数R和列数C(1≤R,C≤100)。下面是R行,每行有C个数,代表高度

(两个数字之间用1个空格间隔)。

Output

输出区域中最长滑坡的长度。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int dx[4]={0,-1,0,1};
 8 int dy[4]={-1,0,1,0};
 9 int f[110][110],g[110][110];
10 int r,c,ans;
11 
12 inline int dfs(int x,int y)
13 {
14     int nx,ny,t;
15     if(f[x][y]!=0) return f[x][y];
16     t=1;
17     for(int i=0;i<4;i++)
18     {
19         nx=x+dx[i];ny=y+dy[i];
20         if(nx>=1&&nx<=r&&ny>=1&&ny<=c&&g[nx][ny]>g[x][y])
21         {
22             int tmp=dfs(nx,ny)+1;
23             if(tmp>t) t=tmp;
24         }
25     }
26     f[x][y]=t;
27     return  t;
28 }
29 
30 int main()
31 {
32     int t;
33     scanf("%d%d",&r,&c);
34     for(int i=1;i<=r;i++)
35         for(int j=1;j<=c;j++)
36             scanf("%d",&g[i][j]);
37     memset(f,0,sizeof(f));
38     for(int i=1;i<=r;i++)
39         for(int j=1;j<=c;j++)
40         {
41             t=dfs(i,j);
42             f[i][j]=t;
43             if(t>ans) ans=t;
44         } 
45     printf("%d",ans);
46     return 0;
47 }
P1434
原文地址:https://www.cnblogs.com/Hoyoak/p/11632047.html