http://poj.org/problem?id=1190

/*
此题是对半径和高的枚举搜索,但要进行剪枝 
*/
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,minv[21],mins[21],best;
void dfs(int M,int v,int s,int r,int h)
{
	int i,j,hmax;
	if(M==0) {
		if(v==n&&s<best) best=s;
		return ;
	}
	if(v+minv[M]>n||s+mins[M]>=best||2*(n-v)/r+s>=best) return ;
	//进行剪枝当前体积与剩下M层的最小体积大于n
	//侧面积与剩下M层的最小侧面积大于等于best
	/*剩下M层的侧面积为lefts=2*(r[k]*h[k]+...+r[m]*h[m]) , k=(M+1,..,m)
	lefts>2*(n-v)/r; lefts=best-s; 
	 */
	for(i=r-1;i>=M;i--)
	{
		if(M==m) s=i*i;
		hmax=min((n-v)/(i*i),h-1);
		for(j=hmax;j>=M;j--)
		dfs(M-1,v+i*i*j,s+2*i*j,i,j);
	}
}
int main(int argc, char *argv[])
{
	int i,rmax,hmax;
    minv[0]=0; mins[0]=0;
	for(i=1;i<21;i++)
	mins[i]=mins[i-1]+2*i*i,minv[i]=minv[i-1]+i*i*i;
	//数组mins,minv记录在该层的最小面积和体积,在等于i时取得; 
	while(cin>>n>>m)
	{
	rmax=sqrt(1.0*n)+1;
	hmax=n/(m*m)+1;
	best=1000000;
	dfs(m,0,0,rmax,hmax);
	if(best==1000000) best=0;
	cout<<best<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值