1190

/*
pi*R1*R1*H1+pi*R2*R2*H2+...= N*pi

pi*M*R1*R1*H1 > N*pi > pi*M*Rm*Rm*Hm

Q = S*pi = ( 2*pi*R1*R1 + 2*pi*R1*H1 ) + (  ) + ...

R^2*H<=1000

R = 1,H <= 1000
R = 2,H <= 250
R = 3,H <= 110
R = 4,H <= 
...
R = 31, H <= 1 

首先枚举R,H.
针对此题,有三个优化,一个是体积的下限,还有两个面积的下限
其中面积优化条件,把剩余的体积转化为圆柱体,这个面积作为面积的下限。这个优化条件还没想明白,不过感觉应该是对的。比把体积转化为多个圆柱体的侧面积之和要小。

想到了,是这样的

加入最后的k到M层有

2*(r[k]*r[k]*h[k]+r[k+1]*r[k+1]*h[k+1]+...+r[M]*r[M]*h[M]) = 2*retv
两边除以当前的最大半径
有
2*(r[k]*h[k]+r[k+1]*h[k+1]+....) > 2*retv/r[k];
左边是实际的面积大于右边的,所以可以拿右边的面积作为面积的下限

*/

// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>

#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>

using namespace std;

// typedef
typedef __int64 LL;

// 
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)

#define Z(a,b) ((a)<<(b))
#define Y(a,b) ((a)>>(b))

const double eps = 1e-6;
const double INFf = 1e100;
const int INFi = 1000000000;
const LL INFll = (LL)1<<62;
const double Pi = acos(-1.0);

template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
	if(x>y) return x;
	return y;
}
template<class T> inline T TMIN(T x,T y)
{
	if(x<y) return x;
	return y;
}
template<class T> inline T MMAX(T x,T y,T z)
{
	return TMAX(TMAX(x,y),z);
}
template<class T> inline T MMIN(T x,T y,T z)
{
	return TMIN(TMIN(x,y),z);
}
template<class T> inline void SWAP(T &x,T &y)
{
	T t = x;
	x = y;
	y = t;
}


// code begin
int N; // 体积
int M; // 层数
int ans;
int minv[22];
int mins[22];

void dfs(int retv,int pR,int pH,int lay,int area)
{
	if(lay==0)
	{
		if(retv==0 && area<ans)
			ans=area;
		return;
	}
	
	if(retv<minv[lay] || area+mins[lay]>=ans || area+2*retv/pR>=ans) //最后一个优化是把retv转化为一个圆柱体的侧面积。这三个优化条件是缺一不可的
		return;

	// 根据当前体积,求出半径上限
	int upR = (int)sqrt(retv+0.0),upH,v,a,vl,al;
	if(upR>=pR)
		upR = pR-1;

	for(int i=upR;i>=lay;i--) //枚举半径
	{
		upH = retv/(i*i);
		if(upH>=pH)
			upH = pH-1;
		
		for(int j=upH;j>=lay;j--)
		{
			//
			v = i*i*j;
			if(lay==M) a = 2*i*j+i*i;
			else a = 2*i*j; 

			if(retv-v>=0)
			{
				//printf("半径:%d,高度:%d\n",i,j);
				dfs(retv-v,i,j,lay-1,area+a);
			}
		}
	}
}

int main()
{
	read;
	write;
	for(int i=1;i<=20;i++)
	{
		minv[i] = minv[i-1]+i*i*i;
		mins[i] = mins[i-1]+2*i*i;
	}
	while(scanf("%d %d",&N,&M)==2)
	{
		//
		ans = INFi;
		dfs(N,INFi,INFi,M,0);
		if(ans!=INFi) printf("%d\n",ans);
		else printf("0\n");
	}
	return 0;
}

posted @ 2011-04-22 16:10  AC2012  阅读(155)  评论(0编辑  收藏  举报