题目:
https://www.luogu.org/problem/show?pid=1731
加了四个剪枝;
明确枚举的对象——每层的高度和半径;
∑表面积=∑圆柱侧面积+最大的底面积;(画图);
总结:
注意细节;
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
int V,n,ans=1<<23;
int minV[1001],minA[1001];
int calc(int tot,int r,int h)
{//每一层都为最大体积的情况,
int v=0;
for(int i=0;i<tot;i++)//h,r每次只减1;
v+=(r-i)*(r-i)*(h-i);
return v;
}
void dfs(int v,int tot,int r,int h,int s)
{
if(tot==0)
{
if(v) return;
ans=min(s,ans);
return;
}
if(v<=0) return;
if(s+minA[tot]>=ans) return;//前面的面积+当前最小面积>答案
if(minV[tot]>v) return;//剩余体积<当前最小体积都无法更新;
if(calc(tot,r,h)<v) return;//剩余层数"用最大的体积"仍小于剩余体积
if(r<tot || h<tot) return;//r,h至少等于层数;
for(int i=r;i>=tot;i--)//半径;
{
if(tot==n) s=i*i;
for(int j=h;j>=tot;j--)//高度;
dfs(v-i*i*j,tot-1,i-1,j-1,s+2*i*j);
}
return;
}
void solve()
{
scanf("%d%d",&V,&n);
for(int i=1;i<=n;i++)//预处理每层最小体积与面积.方便剪枝;
minV[i]=minV[i-1]+i*i*i,minA[i]=minA[i-1]+2*i*i;
if(minV[n]>V) {cout<<0<<endl;return;}
// cout<<minV[n]<<endl;
int maxH=(V-minV[n-1])/(n*n)+1;//V-minV[n-1]为最大体积,n为最小半径;
int maxR=sqrt((double)(V-minV[n-1])/n)+1;//同理;
dfs(V,n,maxR,maxH,0);
if(ans== 1<<23 ) cout<<"0";
else cout<<ans;
}
int main()
{
solve();
return 0;
}