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;
}

發佈了54 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章