大致说明: 如果下边一层的半径、高确定,本层及以上的总体积、层数确定,显然这层及以上的最小面积确定。
从而可以以这四个参数定义状态进行四维的记忆化优化。(虽然很吃空间但不至于炸MLE)
现在的问题是:这种记忆化搜索的最终答案只有完全搜完才会出。而最优剪纸的最小面积那个需要将现在正在搜的面积与以前搜出面积比较。这导致了本蒟蒻想不出如何将该剪纸嵌入代码中。
#include<iostream>
using namespace std;
int minn_v[105];
int minn_s[105];
int dp[100005][16][16][16];
int dfs(int v,int layer,int lh,int lr,int nows)
{
// cout<<"i";
if(dp[v][layer][lh][lr]>0)
{
return dp[v][layer][lh][lr];
}
int minn=999999999;
if(layer==1)
{
for(int r=1;r<lr;r++)
{
if(v%(r*r)==0&&v/(r*r)<lh)
{
minn=min(minn,2*r*(v/(r*r)));
}
}
dp[v][layer][lh][lr]=minn;
return minn;
}
for(int r=layer;r<lr&&v>=(r*r);r++)//
{
for(int h=layer;h<lh&&v-h*r*r>=minn_v[layer-1];h++)//
{
if(minn_s[layer-1]+2*r*h>=minn)
continue;
minn=min(dfs(v-h*r*r,layer-1,h,r,nows+2*r*h)+2*r*h,minn);
}
}
dp[v][layer][lh][lr]=minn;
return minn;
}
int main()
{
int n,m,minns=999999999;
cin>>n>>m;
if(m==1)
{
for(int r=1;n/(r*r)>=1;r++)
{
if(n%(r*r)==0)
{
int h=n/(r*r);
minns=min(minns,r*r+2*r*h);
}
}
cout<<minns;
return 0;
}
for(int i=1;i<=m;i++)
{
minn_v[i]=minn_v[i-1]+i*i*i;
}
for(int i=1;i<=m;i++)
{
minn_s[i]=minn_s[i-1]+2*i*i;
}
for(int r=m;n>=(r*r);r++)
{
for(int h=m;n-h*r*r>minn_v[m-1];h++)
{
minns=min(minns, dfs(n-h*r*r,m-1,h,r,r*r+2*r*h) + r*r + 2*r*h);
}
}
if(minns==999999999)
{
cout<<0;
return 0;
}
cout<<minns;
return 0;
}