1. 程式人生 > >洛谷P1731 [NOI1999]生日蛋糕

洛谷P1731 [NOI1999]生日蛋糕

nbsp 最優 ext 一個 code pan ins 如果 oid

題目大意

制作體積為Nπ的M層蛋糕,要求從上到下半徑遞減,高遞減。輸出使表面積Sπ最小的S。(N<=20000)(M<=15)。

思路:

搜索,以下是幾個剪枝:

  • 以後按最小搭建,余下的也體積不夠,舍去。
  • 以後按最大搭建,余下的體積還有多余,舍去。
  • 以後表面積的最小值加上也比當前最優解大,舍去。
  • 半徑的枚舉順序非常關鍵,要從大到小。因為半徑對體積影響大,當半徑較大時,高可以少枚舉一點,更新mins也更早(如果rh都很小,會循環好幾次知道r,h足夠大才更新mins)。
 1 #include<cstdio>
 2 #include<cstring>
 3
#include<algorithm> 4 #include<cmath> 5 6 using namespace std; 7 8 int n,m,lifang[5000],s,mins,cnt[60],te; 9 10 void init() 11 { 12 lifang[1]=1; 13 for(int i=2;i<=m;i++) 14 { 15 lifang[i]=lifang[i-1]+i*i*i; 16 } 17 return ; 18 } 19 20 void dfs(int ceng,int
tiji,int rr,int hh) 21 { 22 if(ceng==m+1) 23 { 24 if(tiji==0) 25 { 26 mins=min(mins,s); 27 } 28 return ; 29 } 30 if(tiji-lifang[m-ceng+1]<0)return ;//以後按最小搭,余下的也體積不夠。 31 if(ceng!=1) 32 { 33 long long tem=0;//以後按最大搭,余下的體積還有多余。 34
for(int i=1;i<=m-ceng+1;i++) 35 { 36 tem+=(rr-i)*(rr-i)*(hh-i); 37 } 38 if(tiji>tem)return ; 39 } 40 int t1,t2,t3; 41 t2=m-ceng+1;//最小值 42 if(s+t2*(t2+1)*(2*t2+1)/3>=mins)return ;//以後表面積的最小值加上也比當前最優解大。 43 t1=sqrt((tiji-lifang[t2-1])/t2);//半徑最大值。 44 t1=min(rr-1,t1); 45 t3=(tiji-lifang[t2-1])/(t2*t2);//高最大值 46 t3=min(hh-1,t3); 47 if(t2>t1)return ; 48 if(t2>t3)return ; 49 for(int r=t1;r>=t2;r--)//這個枚舉順序非常關鍵 50 { 51 for(int h=t2;h<=t3;h++) 52 { 53 s+=(h*r*2); 54 if(ceng==1)s+=r*r; 55 if((s>mins)||(tiji-r*r*h<lifang[t2-1]))//同第三個和第一個剪枝 56 { 57 s-=(h*r*2); 58 if(ceng==1)s-=r*r; 59 break; 60 } 61 dfs(ceng+1,tiji-r*r*h,r,h); 62 s-=(h*r*2); 63 if(ceng==1)s-=r*r; 64 } 65 } 66 return ; 67 } 68 69 int main() 70 { 71 scanf("%d%d",&n,&m); 72 mins=0x7fffffff; 73 init(); 74 dfs(1,n,mins,mins); 75 if(mins==0x7fffffff) 76 { 77 printf("0\n"); 78 return 0; 79 } 80 printf("%d\n",mins); 81 return 0; 82 }

洛谷P1731 [NOI1999]生日蛋糕