解题:NOI 1999 生日蛋糕

题面

裸的搜索题,就说剪枝(注:nw->noww->当前,res->rest->剩余):

1.想达到$Nπ$的体积,那么半径一开始最多也就$sqrt(n)$了,再大就超了。。。

2.可以预处理$minv[i]$表示还剩$i$层时最少还要放多少的体积,当当前体积$+minv[res]>n$时剪掉

3.每次枚举高度时从$n-V_{nw}-minv[res-1]$枚举,这是这一层高的高度,再高就超了。。。

4.上面的那些都是小弟弟,这个是最强的(雾

∵$S_{res}=2*\sum\limits_{i=nw}^{m}r_i*h_i$,$V_{res}=\sum\limits_{i=nw}^{m}{r_i}^2*h_i$

∴$S_{res}=\sum\limits_{i=nw}^{m}\frac{2*V_{i}}{r_i}$

∴$S_{res}>=\frac{2*V_{res}}{r_{nw}}$

加了之后跑的飞起=。=

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int minv[20],mins[20];
 7 int n,m,s,maxx;
 8 void prework()
 9 {
10     minv[1]=mins[1]=1;
11     for(int i=2;i<=16;i++)
12         minv[i]=minv[i-1]+i*i*i,mins[i]+=i*i;
13 }
14 inline int mini(int a,int b)
15 {
16     return a<b?a:b;
17 }
18 void DFS(int lasr,int lash,int res,int noww,int area)
19 {
20     if(!res) {if(noww==n&&s>area) s=area; return ;}
21     if(noww+minv[res]>n) return ; 
22     if(res!=m&&2*(n-noww)/lasr>=s-area) return ;
23     for(int i=lasr-1;i>=res;i--)    
24     {
25         int maxh=mini(n-noww-minv[res-1],lash-1); 
26         for(int j=maxh;j>=res;j--)
27             DFS(i,j,res-1,noww+i*i*j,area+2*i*j+(res==m)*i*i);
28     }
29 }
30 int main ()
31 {
32     scanf("%d%d",&n,&m);
33     maxx=sqrt(n)+2,s=1e9;
34     prework(),DFS(maxx,maxx,m,0,0); 
35     printf("%d",(s==1e9)?0:s);
36     return 0;
37 } 
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/9779353.html
今日推荐