要製作乙個體積為nπ的m層生日蛋糕,每層都是乙個圓柱體。 設從下往上數第i(1 <= i <= m)層蛋糕是半徑為ri, 高度為hi的圓柱。當i < m時,要求ri > ri+1且hi > hi+1。
由於要在蛋糕上抹忌廉,為盡可能節約經費,我們希望蛋糕外表面(最下一層的下底面除外)的面積q最小。
令q = sπ
請程式設計對給出的n和m,找出蛋糕的製作方案(適當的ri和hi的值),使s最小。 (除q外,以上所有資料皆為正整數)
· ·
·
列舉每一層可能的高度和半徑。
·
·
底層蛋糕的最大可能半徑和最大可能高度
·
·
從底層往上搭蛋糕,而不是從頂層往下搭 在同一層進行嘗試的時候,半徑和高度都是從大到小試
·
·1:搭建過程中發現已建好的面積已經超過目前求得的最優表面積,或者預見到搭完後面積一定會超過目前最優表面積,則停止搭建 (最優性剪枝)
2:搭建過程中預見到再往上搭,高度已經無法安排,或者半徑已經無法安排,則停止搭建(可行性剪枝)
3:搭建過程中發現還沒搭的那些層的體積,一定會超過還缺的體積,則停止搭建(可行性剪枝)
4:搭建過程中發現還沒搭的那些層的體積,最大也到不了還缺的體積,則停止搭建(可行性剪枝) · ·
1)用陣列存放 maxvfornrh(n,r,h) 的計算結果,避免重複計算
2)加上對本次dfs失敗原因的判斷。如果是因為剩餘體積不夠大而失敗,那麼就用不著試下乙個高度,直接break; 或者由小到大列舉 h · ·
#include
#include
#include
#include
using
namespace
std;
int n, m;
int minarea = 1
<< 30;
int area = 0;
int minv[30];
int mina[30];
int minnrh[30][30][30];
int maxvfornrh(int n, int r, int h)
int dfs(int v, int n, int r, int h)
}if (v <= 0)
return
0; if (minv[n] > v) //剪枝3
return
0; if (area + mina[n] >= minarea) //剪枝1
return
0; if (h < n || r < n) //剪枝2
return
0; if (maxvfornrh(n, r, h) < v)
//剪枝4 //這個剪枝最強!沒有的話,5秒都超時,有的話,10ms過!
return -1;
//for( int rr = n; rr <= r; ++ rr ) 這種寫法比從大到小慢5倍
for( int rr = r; rr >=n; -- rr )
}}int main(void)
if (minv[m] > n)
printf("0\n");
else
return
0;}
剪枝搜尋心得
前天在 程式設計之美 中讀到乙個 一摞烙餅排序 的問題,第一眼不會做,看了答案之後倒是讓我明白了一年多之前不真正理解的剪枝搜尋的內涵。記錄一下,作為分享和溫習之地。void cprefixsorting search int pcakesarray,int step if issorted pcak...
搜尋剪枝DFS
tempter of the bone hdu1010 題意 給乙個圖,找出乙個看能否能在t的時間內從s到達d點 思路 bfs肯定不行,因為bfs找到的是最短時間的路徑,無法對在t時間點到達d點進行判斷 於是才想到了dfs,這個能把所有的情況遍歷一遍的演算法,雖然圖的長寬只有7,但是總是超時,這次終...
DFS搜尋 剪枝
hdu 5952 題意 給出一張無向圖,然後判斷這張圖中一共有多少個不同的大小為s的完全圖 完全圖的頂點數為s個 題目保證每個點的度不大於20。完全圖 n個點兩兩之間都有一條邊的圖叫完全圖。思路 由於頂點個數很少,而且每個點的度數最多是20,所以可以暴力優化,建圖,對於每個s點完全子圖,如果i點在子...