zoukankan      html  css  js  c++  java
  • 高级算法--深搜

    下面是一本通OJ上题目的代码实现

    ·例一:

    题目描述:

    将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。

    例如:n=7,k=3,下面三种分法被认为是相同的。

    1,1,5; 1,5,1; 5,1,1;

    问有多少种不同的分法。 输出一个整数,即不同的分法。

    代码实现:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 int n,k;
     5 int f[210][7];
     6 int main()
     7 {
     8     scanf("%d%d",&n,&k);
     9     memset(f,0,sizeof(f)); //f数组先初始化为0,
    10     f[0][0]=1;//但是第一个要为1,为了防止加来加去都是0
    11     for(int i=1;i<=n;i++)//总和的循环
    12         for(int j=i;j<=n;j++)//也是总和的循环,因为前面已经循环了i,所以j可以直接由i开始
    13         //循环两次是为了后面状态的处理做铺垫
    14             for(int x=1;x<=k;x++)//这是循环方案数
    15             {
    16                 f[j][x]=f[j][x]+f[j-i][x-1];//f[j][x]就是方案总数的最大值
    17                 //j-i是为了防止重复,比如说:1 1 5,1 5 1,5 1 1 这样的情况出现
    18                 //x-1就是上一个的最大值,是为了继承的
    19             }
    20     printf("%d
    ",f[n][k]);//输出最大值
    21     return 0;
    22 }

    ·例二:

    题目描述:

      7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。设从下往上数第i(1≤i≤M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i<M时,要求Ri>Ri+1且Hi>Hi+1。由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。

    令Q=Sπ,请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。

    (除Q外,以上所有数据皆为正整数)

    代码实现:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;      
     5 int n,m,minn=2e+9; //min表为面积最小的值,初始化为一个极大值
     6 void dfs(int d,int v,int s,int r,int h)
     7 //前d层蛋糕体积为v 表面积为s 第d层半径r 高度h 
     8 {
     9     if(d==m)//前d层就是m层,表示我们已经搜索完了    
    10      {
    11         if(v==n)minn=s;//如果体积也符合题目要求的话,更新表面积的最小值 
    12         return;//返回值 
    13      }
    14     if(v+(r-1)*(r-1)*(h-1)*(m-d)<n)return;
    15     /*
    16     1.如果当前体积加上之后每层的最大值,还比题目要求的体积小,直接结束该趟递归
    17     2.我在主函数当中讲了我们的搜索是自下而上,所以下面一层比上面一层要小
    18     3.为什么说是最大值呢?因为我们选取的是当前上一层的半径,而且越往上越小
    19     而我们乘以的同样也是那么多层,所以说这个是最大值
    20     */ 
    21     if(v+m-d>n)return;           
    22     /*
    23     1.如果当前体积加上之后每层的最小值,还比题目要求的体积大,直接结束该趟递归
    24     2.为什么说是最小值呢?因为我们的上一层是比下面的那一层要小的,也就是最顶上的
    25     可能半径就为1,是最小的,既然是最小的说明下面的就比他要大,但是我们就直接
    26     最小半径的平方1*1*(m-d)也就是层数,那么可能会疑惑高去哪里了?
    27     高也是假设了最小的1,所以整个半径平方乘以高乘以层数=1*1*1*(m-d)=m-d
    28     */
    29     if(2*(n-v)/r+s>=minn)return;  
    30     /*
    31     如果求解过程半途找到比当前最小值,也就是minn的值还大的数据,结束该趟递归
    32     这一步是最关键的一步但是我不知道现在在这里怎么表示出来 
    33     */ 
    34     for(int i=r-1;i>=m-d;i--)
    35     /*
    36     i(半径)[再上一层的半径]的最小值要保证大于当前这一层半径的最小值
    37     题目解释当中说的至少要大1,也就是说上一层的半径最大是当前这一层的半径-1
    38     也就是r-1
    39     最小的话就是也要大于等于剩下的层数,不然后面的层就没有整数半径
    40     比如说:
    41     总共有5层,当前是第3层(顺数),第3层的半径是5,
    42     那么第2层的半径最大就是4,最小的话就是(5-3)=2
    43     因为只有大于等于2的时候,这一层的上一层才有半径,
    44     如果第2层的半径是1的话,那么至少要大于等于1,也就是第1层的半径小于等于0
    45     这个显然是不可能的 
    46     */
    47     {
    48         for(int j=h-1;j>=m-d;j--)
    49         /*
    50         j(高度)[再上一层的高度]的最小值要保证大于当前这一层高度的最小值
    51         跟半径是同样的道理,这里就不再解释了 
    52         */ 
    53         {
    54             if((i*i*j+v<=n)&&(s+2*i*j<minn))
    55             /*如果我们后面找到的这个半径和高度组合的体积小于等于n*/
    56             /*并且它的面积比我们之前记录过的要小的话*/
    57                 dfs(d+1,v+i*i*j,s+2*i*j,i,j);/*递归搜索子状态,也就是处理下一个*/ 
    58         }
    59     }
    60 }
    61 int main()
    62 {
    63      scanf("%d%d",&n,&m);
    64      for(int i=m;i*i*m<=n;i++)
    65      /*
    66      1.i表示半径,半径的平方(也就是底面积)*层数(也就是体积)
    67      小于要求的体积的话,可以继续
    68      2.i从m开始是因为,底下每一层的高度和半径至少比上一层的大1,
    69      也就是说,最底下一次的半径和高度至少为M了
    70      */
    71      {
    72         for(int j=m;i*i*j<=n;j++)
    73         /*
    74         1.j表示高度,高度乘以底面积小于要求体积,可以继续
    75         2.i从m开始是因为,底下每一层的高度和半径至少比上一层的大1,
    76         也就是说,最底下一次的半径和高度至少为M了 
    77         */ 
    78         {
    79             if(i*i+2*i*j<minn)/*小于我们一直更新的最小值,才传入*/ 
    80             dfs(1,i*i*j,i*i+2*i*j,i,j);
    81             /*
    82             从第m层开始,我们之前的枚举是自下而上,所以在搜索中也是自下而上
    83             注意:(分开五个来分析) 
    84             (1)从前1层开始 
    85             (2)体积是半径*半径*高 
    86             (3)表面积不单单是侧面积,最底下那一层的表面积 
    87             (4)i表示半径
    88             (5)j表示高度 
    89             */ 
    90         }
    91     }
    92     printf("%d
    ",minn);/*输出最小值*/
    93     return 0;
    94 }
    95 /*
    96 体积V=πR*R*H
    97 侧面积A’=2*π*R*H
    98 底面积A=π*R*R
    99 */
  • 相关阅读:
    MYCAT介绍
    MES生产日报存储过程
    HttpContext讲解
    负载均衡session共享问题
    UML学习(二)-----类图
    Hadoop实战第一篇
    网站速度优化的一般方法
    MVC中的ActionResult
    CCF201403-2 窗口(100分)
    CCF201403-2 窗口(100分)
  • 原文地址:https://www.cnblogs.com/juruohqk/p/10991656.html
Copyright © 2011-2022 走看看