深度优先搜索算法的常用优化

由“生日蛋糕”这道题引出。

 

https://www.luogu.org/problemnew/show/P1731

先从题目中提取一些做题可能用得到的信息:

1.从上往下数第i层(i<M)的蛋糕的半径 R总是比 Ri-1 

2.实数计算与本题并没有关系

 

接下来考虑如何做题:

这道题可以用深度优先搜索做,但是为什么呢?

不妨先将题目中出现的各个表达式展开一下

蛋糕的体积为 ,从上往下数第 i 层的体积为 πri2hi , 则整个蛋糕的体积为 Σmi=1   πri2hi。

所以N就是去掉了π的Nπ啦

蛋糕的表面积就是 Σmi=1   2πrihi ,所以题目中的S就是去掉π的此式子

 

此时,可以看出,题目中的一个约束条件:体积Nπ    已经和答案S(乘以一个π)通过 每一层的h和r 链接起来了,

也就是说,当每一层的蛋糕体积加起来的和等于Nπ时,此时的表面积才有可能被接受成最优解。

然而,这个约束条件还不够劲,仔细读一下题目,发现:从上往下数第i层(i<M)的蛋糕的半径 R总是比 Ri-1 小(就是往上数第十二句那一句),

发现这个约束条件真是太给力了,再加上M那较小的数据范围,似乎用搜索做就是顺理成章的事了,再加上一些剪枝,就可以通过本题了。

 


 

 

前面说了,此题目的计算都是在整数范围内的,这大概也是本题可以用搜索做的原因之一吧?

现在时间不多,马上放学,剩下的内容我会在明天补上。

先给出此题的代码:(见后文)

关于这份代码,放在这里的目的是想要说一下,如果将第16和第17行代码中的for语句改成这样:

for(int i = deep; i < r1; ++i)
        for(int j = deep; j < h1; ++j)

程序的效率将会大大降低,原本能通过的程序也会因为此“微不足道”的改动而惨惨TLE,这就涉及到搜索顺序对于程序效率的影响……推荐一篇能够用于参考的文档:《信息学竞赛中搜索问题的常见优化技巧重庆一中  黄晓愉》

(来自2006年全国信息学冬令营讲座)

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,m,s;
 7 int minv[20];
 8 void dfs(int r1, int h1, int nwii, int ns, int deep) {
 9     if(ns >= s) return;
10     if(nwii == n && deep == 0) s = ns;
11     if(nwii >= n || deep == 0) return;
12     
13     if(2*(n-nwii)/r1 + ns >= s) return;
14     if(minv[deep] + nwii > n) return;
15     
16     for(int i = r1-1; i >= deep; --i)
17         for(int j = h1-1; j >= deep; --j) {
18             if(i*i*j + nwii > n) continue;
19             if(deep == m)
20             dfs(i, j, nwii + i*i*j, ns + 2*i*j + i*i, deep - 1);
21             else
22             dfs(i, j, nwii + i*i*j, ns + 2*i*j, deep - 1);
23         }
24 }
25 
26 int main() {
27     s = 200000000;
28     cin>>n>>m;
29     
30     for(int i = 1; i <= m; ++i) {
31         minv[i] = minv[i-1] + i*i*i;
32     }
33     dfs(28 ,28 , 0, 0, m);
34     if(s == 200000000)
35         cout<<0;
36     else
37         cout<<s;
38     return 0;
39 }

 

上一篇:Pushgateway(2)自定义数据推送到pushgateway及推送数据的注意事项


下一篇:Beego框架——01beego安装