我对于搜索算法的慢慢摸索

高中的时候好像什么都没学会的样子,提到搜索脑子里云里雾里一般。还能怎么着,练呗。

找到了一道dfs基础题,http://poj.org/problem?id=1190

果然是完全没有思路,参照大佬的题解,弄懂了大佬的思路。

 1 //生日蛋糕
 2 //poj 1190 
 3 #include<stdio.h>
 4 #include<math.h>
 5 #define INF 1000000
 6 int mins[21],minv[21];//从第一层到第i层的最小体积minv和最小面积mins 
 7 #define min(a,b) ((a)<(b)?(a):(b))
 8 int n,m,best;
 9 void init(){
10     int i;
11     for(i=1;i<21;i++){
12         mins[i]=mins[i-1]+2*i*i;//因为半径和高必须是正整数,又要递增,所以i作为 
13         minv[i]=minv[i-1]+i*i*i; //第i层的半径和高显然是最小的情况。 
14     }
15 }
16 
17 //核心算法:搜索。从第m层开始往上搜索,一直到第0层结束。 
18 // deep表示该层层数,sums是从m到deep+1得到的表侧面积,sumv是体积,r是deep+1的半径,h是deep+1的高度 
19 void dfs(int deep,int sums,int sumv,int r,int h){
20     if(deep==0){
21         if(sumv==n&&sums<best)best=sums;
22         return;
23     }
24     if(sums+mins[deep]>best||sumv+minv[deep]>n||2*(n-sumv)/r+sums>=best)return;
25     //几个剪枝
26     //第一跟第二:表面积显然大于最优解或者是体积显然超过n
27     //第三个:n-sumv=h[1]*r[1]*r[2]+……+h[deep]*r[deep]*r[deep]<h[1]*r[1]*r+……+h[deep]*r[deep]*r
28     //两边同除r,*2,可以化为这样的形式 
29     int i,j,maxh;
30     for(i=r-1;i>=deep;i--){//i是遍历deep层的半径,从最大到最小 
31         if(deep==m)sums=i*i;//sums的初值
32         maxh =min((n-sumv-minv[deep-1])/(i*i),h-1);//从这两个数中寻找maxh的最大值,这两个都是顶点
33         for(j=maxh;j>=deep;j--)dfs(deep-1,sums+2*i*j,sumv+i*i*j,i,j); 
34     }
35 }
36 main(){
37     best=INF;
38     scanf("%d%d",&n,&m);
39     dfs(m,0,0,sqrt(n)+1,n+1);//初始条件m+1层的半径为h等于1时得到的半径,h是r等于1时得到的半径。 
40     if(best==INF)printf("0\n");
41     else printf("%d\n",best);
42     return 0;
43 } 

这道题的主要考点应该是第三处剪枝(大佬是这么说的),但是与我而言,我连最基础的搜索的板子都不会。还能怎么着,练呗。

猜你喜欢

转载自www.cnblogs.com/liuxinyu/p/9372781.html
今日推荐