深搜剪枝技巧
深搜的剪枝技巧
不会搜索的这里→搜索与回溯
一、什么是剪枝
剪枝,顾名思义,就是通过某种判断,避免一些不必要的搜索。在编写程序时,一般都要考虑剪枝
显而易见,优化的核心在于设计剪枝判断方法决定哪些应该舍去,那些不该舍。
二、剪枝原则
- 正确性:剪枝的目的是优化程序,但如果将正解减去,那优化就失去意义了。
- 准确性:在正确的基础上,尽量剪去更多的不能通向正解的枝条。
- 高效性:也就是不能比不剪枝时间复杂度要高。
三、几种剪枝技巧
数的划分
首先面临的问题是如何将相同的分法删掉,其次就是时间复杂度。
可以考虑,每一次都搜索大于等于上一次的数,不仅可以避免相同的分法,还可以剪枝,
在一个剪枝就是,如果选第t个之前的值为m,那么第k个数必然不能大于(n-m)/(k-t+1) //因为还没选第t个数,故考虑+1;
不然根据我们原则,后面选的数必须大于前面选的数,肯定会超过n。
最后一个小优化,如果选完k-1个数了,那第k个数是什么就已经定了,不需要再去枚举,只需看它是否符合原则。
分析过后,代码应不难想出
#include<iostream>
using namespace std;
int n,k,ans;
int a[1000];
void search(int t)
{
if(n==0)
return ;
if(t==k)
{
if(n=a[t-1])
ans++;
return ;
}
for(int i=a[t-1];i<=n/(k-t+1);i++) //剪枝,若i比n/(t-k+1)大,则后面即使取能取到的最小值,也会大于n;
{
n-=i;
a[t]=i;
search(t+1);
n+=i;
}
}
int main()
{
cin>>n>>k;
a[0]=1;
search(1);
cout<<ans;
}
[SHOI2002]滑雪
普及/提高-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
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-\ldots…-33-22-11 更长。事实上,这是最长的一条。
输入格式
输入的第一行为表示区域的二维数组的行数 RR 和列数 CC。下面是 RR 行,每行有 CC 个数,代表高度(两个数字之间用 11 个空格间隔)。
输出格式
输出区域中最长滑坡的长度。
输入输出样例
输入 #15 5 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输出 #125
这题就是记忆化搜索
我们将样例放大
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
其实非常简单,只是算法比较难想,我一开始按DP做的,没做出来,后来在发先记忆化搜索可以。
#include<iostream> #include<cstdio> using namespace std; int r,c,ans; int a[10000][10000],f[10000][10000],dx[5]={0,1,0,-1,0},dy[5]={0,0,1,0,-1}; int search(int x,int y) { int nx,ny,tmp; if(f[x][y]>0) return f[x][y]; int t=1; for(int i=1;i<=4;i++) { nx=x+dx[i]; ny=y+dy[i]; if(nx<=r&&nx>=1&&ny<=c&&ny>=1&&a[nx][ny]>a[x][y]) { tmp=search(nx,ny)+1; if(tmp>t) t=tmp; } } f[x][y]=t; return (t); } int main() { cin>>r>>c; for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) cin>>a[i][j]; for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) { f[i][j]=search(i,j); if(f[i][j]>ans) ans=f[i][j]; } printf("%d",ans); }
最后来道难亿点的题——→小木棍