題解P0006:生日蛋糕(P1731)
阿新 • • 發佈:2022-03-20
這道題居然是1999年省選題!這可能是洛谷藍題裡最水的了。。。
題目連結:https://www.luogu.com.cn/problem/P1731 大家有興趣可以去看看
題目描述:就是類似這樣一個蛋糕:
現在給它體積和層數,為了省奶油,要求它最小表面積(不算底面)
題目思路:深搜剪枝,從下到上列舉每層的半徑和高,最終求出最小表面積(具體思路和剪枝詳見程式碼註釋)
程式碼:
#include<bits/stdc++.h>
using namespace std;
int r[21],h[21],n,m,we=0x3f3f3f3f;//定義陣列儲存半徑和高是為了省事
void dfs(int v,int s,int k,int p){//v:體積;s:表面積;k和p:層數(一個倒著的一個正著的)
int i,j;
//下面是剪枝,可以最後看
if(v<0){//體積超了
return;//返
}
if(k<0){//層數超了
return;//返
}
if(s+k+r[1]*r[1]>we){//表面積超了當前最小值,再往下搜沒意義了
return;//返
}
if(v>r[p-1]*r[p-1]*h[p-1]*k){//假設之後的體積全=當前體積,還是不夠
return;//返
}
//剪枝結束
if(k==0&&v==0){//滿足條件
s+=r[1]*r[1];//加上最下面的底面積(=所有層有用的底面積)
we=min(we,s);//取最小值
return;
}
for(i=r[p-1]-1;i>=k;i--){//列舉半徑(i的初始值是上一層-1)
for(j=h[p-1]-1;j>=k;j--){//列舉高
if(v>=i*i*j&&k>=0){
r[p]=i;
h[p]=j;
dfs(v-i*i*j,s+2*i*j,k-1,p+1);//v減去當前層體積,s加上側面積
r[p]=i;//回溯
h[p]=j;
}
}
}
}
int main(){
cin>>n>>m;
h[0]=int(sqrt(n));
r[0]=int(sqrt(n));//手動確定最底層高和半徑的最大值
dfs(n,0,m,1);
if(we==0x3f3f3f3f){//若值不變
cout<<0;//輸出0
}else{
cout<<we;
}
return 0;
}