http://poj.org/problem?id=1190
经典的搜索, 题目因为比较复杂就不形容了,这里说下剪枝的技巧:
剪枝1 :在第i层的时,若i+1 -- n 层取最小, 总体积大于N ,则剪枝 ;
剪枝2 :在第i层的时,若i+1 -- n 层取最小, 总表面积大于ans ,则剪枝 ;
剪枝3 : 因为前i层的体积为sumv,那么剩余的m-i层的体积满足:n-sumv=(h[k]*(r[k]^2)+……+h[1]*(r[1]^2)) ,(k = i...1) ;而剩余部分的表面积满足:lefts=2*(r[k]*h[k]+……+r[1]*h[1])>2*(n-sumv)/r[i] ,(k = i...1) ; 显然有上述不等式lefts=best-sums>2*(n-sumv)/r,即2*(n-sumv)/r+sums<best,所以当2*(n-sumv)/r[i]+sums>=best时也可以进行剪枝. ----------------------神级剪枝, 没有想到
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
int n ,m ;
int ans ;
int mins[21] ,minv[21] ;
const int INF = 0x7fffff ;
void dfs( int k,int sums,int sumv,int r, int h ){
if( k == 0 ){
if( sumv == n && ans > sums )
ans = sums ;
return ;
}
if( minv[ k ] + sumv > n) return ;
if( mins[ k ] + sums >= ans ) return ;
if( 2 * (n - sumv)/r + sums >= ans) return ;
int rr ,hh ;
for( rr = r - 1 ; rr >= k ; rr--){
if(k==m){
sums = rr *rr ;
}
for(hh= h -1 ; hh>=k;hh--){
dfs(k-1,sums+2*rr*hh,sumv+rr*rr*hh,rr,hh);
}
}
}
int main(){
scanf("%d %d",&n,&m);
mins[0] = minv[0] = 0 ;
for(int i=1;i<=m;i++){
mins[i] = mins[i-1] + 2 * i * i;
minv[i] = minv[i-1] + i * i * i ;
}
ans = INF ;
int r = (int)sqrt(n - minv[m-1]) + 2 ;
int h = n - minv[m-1] + 1 ;
dfs( m , 0 , 0 , r , h ) ;
if(ans == INF)
ans = 0 ;
printf("%d\n",ans);
return 0;
}