#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stack>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <map>
#include <string>
#include <stdlib.h>
#include <vector>
int N,M;
using namespace std;
int minArea = 1<<30;
int Area;
int minV[25];//n层蛋糕的最小体积
int minA[25];//n层蛋糕的最小侧面积
int maxVforNRH(int n,int r,int h)//最底层半径为r,高度为h的n层蛋糕最大的体积
{
int v=0;
for(int i=0;i<n;i++)
{
v+=(r-i)*(r-i)*(h-i);
}
return v;
}
void dfs(int v,int n,int r,int h)//要搭体积为v的n层蛋糕,最底层半径不超过r,高度不超过h
{
if(n==0)
{
if(v)
return;
else
{
minArea = min(minArea,Area);
return ;
}
}
if(v<0)
return;
if(maxVforNRH(n,r,h)<v)//预见可行性剪枝
return;
if(Area+minA[n]>minArea)//预见最优性剪枝
return;
if(h<n||r<n)//预见可行性剪枝
return;
for(int rr=r;rr>=n;rr--)
{
if(n==M)
Area = rr * rr;//摆最下面一层时,底面积已经确定
for(int hh=h;hh>=n;hh--)
{
Area+=2*rr*hh;
dfs(v-rr*rr*hh,n-1,rr-1,hh-1);
Area-=2*rr*hh;
}
}
}
int main()
{
cin >> N >> M;//m层蛋糕体积为n
minV[0] = 0;
minA[0] = 0;
for(int i=1;i<=M;i++)
{
minV[i] = minV[i-1]+ i*i*i;//每层小蛋糕都保证是最小的体积和高度
minA[i] = minA[i-1]+2*i*i;
}
if(minV[M]>N)
cout<<"0"<<endl;
else
{
int maxR = sqrt((N-minV[M-1])*1.0/(1.0*M)) + 1;
int maxH = (N-minV[M-1])/(M*M) + 1;
Area = 0;
dfs(N,M,maxR,maxH);
if(minArea < (1<<30) )
cout << minArea<<endl;
else
cout<<"0"<<endl;
}
return 0;
}
深搜+剪枝 生日蛋糕
最新推荐文章于 2022-05-04 14:51:35 发布