题目链接: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 ",ans); 38 return 0; 39 }