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

2014-11-23 20:00:38 · 作者: · 浏览: 6
/*
此题是对半径和高的枚举搜索,但要进行剪枝 
*/
#include 
#include 
#include 
#include 
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&&sn||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<