zoukankan      html  css  js  c++  java
  • 搜索的优化

    搜索的优化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
  • 相关阅读:
    重读SQLServer技术内幕 -- 故障检测概要
    Android Studio调试React Native项目
    Android 异常处理
    第一天
    记一次"未将对象引用设置到对象的实例"问题的排查过程
    Hyper-V连接虚拟机异常,“无法进行连接,因为可能无法将凭据发送到远程计算机”
    关于TFS2012无法发送警报邮件的问题
    BaseAdapter日常的封装
    android自定义拍照
    Android系统拍照源码
  • 原文地址:https://www.cnblogs.com/Hoyoak/p/11632047.html
Copyright © 2011-2022 走看看