1. 程式人生 > >解題:NOI 1999 生日蛋糕

解題:NOI 1999 生日蛋糕

min aps inline 當當 這一 lose tps ace color

題面

裸的搜索題,就說剪枝(註: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

解題:NOI 1999 生日蛋糕