点击打开链接http://poj.org/problem?id=1190
#include <iostream>
#include <algorithm>
#include <cmath>
#define M1 30
using namespace std; //Q=Sπ求最小S->外表面最小 = (侧面积面积+底面积(中间部分都投影到底面))最小
int MinA[M1]; //i层 cake的最小表面积
int MinV[M1];
int ans=1<<30,area=0,n,M;
int MaxV(int MaxR,int MaxH,int m)
{
int v=0;
for(int i=0;i<m;i++)
{
v+=(MaxR-i)*(MaxR-i)*(MaxH-i); //体积最大 每层r和h都最大
}
return v;
}
void dfs(int n,int m,int MaxR,int MaxH)
{
if(m==0)
{
if(n) //m层都搭完了 体积还没完
{
return;
}
else
{
ans=min(ans,area);
}
}
if(n<0) return;
if(MaxR<m||MaxH<m) //可行性cut: 从下往上 r和h递减 (不能为负)
return;
if(MinV[m]>n) //可行性cut:在搭m层最小体积都大于n
return;
if(MaxV(MaxR,MaxH,m)<n) //可行性cut:在搭m层最大体积都到不了n
return;
if(area+MinA[m]>=ans) //最优性cut
return;
int r,h;
for(r=MaxR;r>=m;r--) //选择性少的先搜
{
if(m==M) //底面积
{
area=r*r;
}
for(h=MaxH;h>=m;h--)
{
area+=2*r*h;
dfs(n-r*r*h,m-1,r-1,h-1);
area-=2*r*h;
}
}
}
int main()
{
int i;// m层cake的体积n
cin>>n>>M;
MinA[0]=0;
MinV[0]=0;
for(i=1;i<=M;i++)
{
MinA[i]=MinA[i-1]+2*i*i;
MinV[i]=MinV[i-1]+i*i*i;
}
if(MinV[M]>n) //
{
cout<<0<<endl;
return 0;
}
int MaxH=(n-MinV[M-1])/(M*M)+1;// 最底层的最大高度
int MaxR=sqrt(double(n-MinV[M-1])/M)+1;
dfs(n,M,MaxR,MaxH);//还差体积n 还差m层
if(ans==1<<30)
{
cout<<0<<endl;
}
else
{
cout<<ans<<endl;
}
return 0;
}
本文介绍了一种解决蛋糕堆叠问题的算法实现,通过深度优先搜索策略来寻找构成特定体积所需的最小表面积组合,利用多种剪枝策略提高搜索效率。
2万+

被折叠的 条评论
为什么被折叠?



