1190

剪枝很重要呀。。。

0MS靠RP。。。

思路:

搜索这是肯定的。主要是剪枝。前期有个预处理工作是找各层的极限。就是他不是说各层都是int的正整数吗,还有严格的递增关系。那每层就肯定有个下限或上限(随便怎么说了)。p_s, p_v就是做这工作的。看看函数吧:

第一个参数是体积,第二个是高度,第三个是个半径,第四个是个层数,第五个是个表面积。

初始的时候,半径给个最大值,高度也给了最大值。所以之后搜索半径和高度是都是递减搜的。

再说剪枝:

除了我上面说的预处理可以用,还有个就是在每一层都可以估计一下表面积的下限值。剩下的体积是V吧,剩下的面积最少是多少呢,S=V/(2*R*pi),上一层R最大值是知道的,这样S下限有了,可以和之前的min_face比较,剪掉很多枝, 再求下一步的H时,注意取当前H和

V与当前R共同约束的H的最小值。

#include <cstdio> #include <cmath> int min_face=1<<30; int N,M; int S; int p_s[21], p_v[21]; #define min(a,b) (a<b?a:b) void DFS(int V, int H, int R, int plies, int face) { if(0==plies&&0==V) { min_face=min(face, min_face); return; } if(0==plies||face+p_s[plies]>min_face||p_v[plies]>V||2*V/R+face>min_face) return; int start=V-p_v[plies-1]; for(int i=R; i>=plies; --i) { if(plies==M) face=i*i; int jj=min(H,start/i/i); for(int j=jj; j>=plies; --j) { DFS(V-i*i*j,j-1,i-1,plies-1,face+i*2*j); } } } int main() { int start; p_s[0]=1; p_v[0]=0; for(int i=1; i<21; ++i) { p_s[i]=p_s[i-1]+i*i*2; p_v[i]=p_v[i-1]+i*i*i; } while(scanf("%d%d",&N,&M)==2) { min_face=1<<30; start=N-p_v[M]; DFS(N,start/M/M,sqrt(start/M),M,0); if(min_face==1<<30) printf("%d/n",0); else printf("%d/n",min_face); } return 0; }

你可能感兴趣的:(工作)