http://poj.org/problem?id=1190
集训队测试的时候老师找了这样一题,第一眼以为是个DP,但是发现DP的话内存不够用啊,无奈最后没写出来,百度之后发现居然是个搜索,不过对于数学太弱的我来说肯定是想不到的,因为要知道确定体积后把后面的全部做成一个圆柱的时候表面积是最小的。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n, m, minn;
int mins[25],minv[25]; //保存对应深度的最小体积和面积
void Init()
{
minv[0] = 0;
mins[0] = 0;
for(int i = 1; i <= 20; i++){
mins[i] = mins[i-1] + 2*i*i; //i层的蛋糕最底层的最小半径和高度都是i。
minv[i] = minv[i-1] + i*i*i;
}
}
int Dfs(int deep, int sums, int sumv, int maxr, int maxh)//深度,已经算过的面积和体积,最大半径和高度
{
if(deep == 0){
if(sumv == n && sums < minn)
minn = sums;
return 0;
}
if(sumv + minv[deep] > n || sums + mins[deep] > minn || 2*(n - sumv)/maxr + sums >= minn)//剪枝
return 0;
for(int i = maxr; i >= deep; i--){
if(deep == m)
sums = i*i;
for(int k = min((n - sumv - minv[deep-1])/(i*i), maxh); k >= deep; k--){//确定半径求最小高度
Dfs(deep-1, sums+2*i*k, sumv+i*i*k, i-1, k-1);
}
}
}
int main()
{
Init();
//freopen("D:\\7.in", "r", stdin);
while(cin>>n>>m){
minn = 10000000;
Dfs(m, 0, 0, n, n);
if(minn == 10000000)
minn = 0;
cout<<minn<<endl;
}
return 0;
}