POJ 1190 生日蛋糕(DFS+剪枝)

题目链接:http://poj.org/problem?id=1190

 

剪枝:

1.上下界剪枝:

在dep层时,枚举R和H可以在某一个区间里枚举

2.优化搜索顺序:

使用倒序枚举

3.可行性剪枝:

预处理出最小体积和侧面积。

如果当前体积v加上1~dep-1层额最小体积大于N,可以剪枝。

4.最优性剪枝

 

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 using namespace std;
 5 const int INF=0x7f7f7f7f;
 6 const int N=30;
 7 int n,m,ans=INF;
 8 int h[N],r[N],s=0,v=0,minv[N],mins[N];
 9 void DFS(int dep){
10     if(!dep){
11         if(v==n) ans=min(ans,s);
12         return;
13     }
14     for(r[dep]=min((int)sqrt((double)n-v),r[dep+1]-1);r[dep]>=dep;r[dep]--)
15     for(h[dep]=min((int)((double)(n-v)/r[dep]/r[dep]),h[dep+1]-1);h[dep]>=dep;h[dep]--){
16         if(v+minv[dep-1]>n) continue;
17         if(s+mins[dep-1]>ans) continue;
18         if(s+(double)2*(n-v)/r[dep]>ans) continue;
19         if(dep==m) s+=r[dep]*r[dep];
20         s+=2*r[dep]*h[dep];
21         v+=r[dep]*r[dep]*h[dep];
22         DFS(dep-1);
23         if(dep==m) s-=r[dep]*r[dep];
24         s-=2*r[dep]*h[dep];
25         v-=r[dep]*r[dep]*h[dep];
26     }
27 }
28 int main(){
29     scanf("%d%d",&n,&m);
30     minv[0]=mins[0]=0;
31     for(int i=1;i<=m;i++){
32         minv[i]=minv[i-1]+i*i*i;
33         mins[i]=mins[i-1]+i*i;
34     }
35     h[m+1]=r[m+1]=INF;
36     DFS(m);
37     printf("%d\n",ans);
38     return 0;
39 }
AC代码

 

posted @ 2020-11-04 20:21  dfydn  阅读(74)  评论(0编辑  收藏  举报