/*
此題是對半徑和高的枚舉搜索,但要進行剪枝
*/
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,minv[21],mins[21],best;
void dfs(int M,int v,int s,int r,int h)
{
int i,j,hmax;
if(M==0) {
if(v==n&&s<best) best=s;
return ;
}
if(v+minv[M]>n||s+mins[M]>=best||2*(n-v)/r+s>=best) return ;
//進行剪枝當前體積與剩下M層的最小體積大於n
//側面積與剩下M層的最小側面積大於等於best
/*剩下M層的側面積爲lefts=2*(r[k]*h[k]+...+r[m]*h[m]) , k=(M+1,..,m)
lefts>2*(n-v)/r; lefts=best-s;
*/
for(i=r-1;i>=M;i--)
{
if(M==m) s=i*i;
hmax=min((n-v)/(i*i),h-1);
for(j=hmax;j>=M;j--)
dfs(M-1,v+i*i*j,s+2*i*j,i,j);
}
}
int main(int argc, char *argv[])
{
int i,rmax,hmax;
minv[0]=0; mins[0]=0;
for(i=1;i<21;i++)
mins[i]=mins[i-1]+2*i*i,minv[i]=minv[i-1]+i*i*i;
//數組mins,minv記錄在該層的最小面積和體積,在等於i時取得;
while(cin>>n>>m)
{
rmax=sqrt(1.0*n)+1;
hmax=n/(m*m)+1;
best=1000000;
dfs(m,0,0,rmax,hmax);
if(best==1000000) best=0;
cout<<best<<endl;
}
return 0;
}
http://poj.org/problem?id=1190
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.