1. 程式人生 > >noi1999 生日蛋糕

noi1999 生日蛋糕

include sqrt string mes bsp 第一個 dfs 我們 希望

題目背景

7月17日是Mr.W的生日,ACM-THU為此要制作一個體積為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外,以上所有數據皆為正整數)

題目描述

技術分享

輸入輸出格式

輸入格式:

有兩行,第一行為N(N<=20000),表示待制作的蛋糕的體積為Nπ;第二行為M(M<=15),表示蛋糕的層數為M。

輸出格式:

僅一行,是一個正整數S(若無解則S=0)。

輸入輸出樣例

輸入樣例#1:
100
2
輸出樣例#1:
68
分析:裸搜只有10分。。。。。。其實這就是一道搜索的題,關鍵是要怎麽剪枝。可以很容易想出兩個剪枝:
1.當前體積+以後的最小體積>n,剪枝.
2.當前表面積+以後的最小表面積>ans,剪枝.
第一個是很好處理的,關鍵是第二個剪枝,如果直接用最小的i和h來算,在體積上不能保證滿足要求,有一個定理是如果體積一定,半徑越大,表面積越小,因為在體積中半徑的增長是平方級的,這樣我們接下來每一層和這一層的半徑相同,那麽就是最小表面積了(雖然永遠也達不到,但是不會把正解給剪掉),保證體積滿足要求,我們只需要用剩下的體積除以當前層的半徑就好了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

const int inf = 0x7ffffff;

int n,m,ans = inf,qs[50],qv[50];

void dfs(int cnt,int s,int v,int r,int h)
{
    if (cnt == 0)
    {
        if (v == n)
        ans 
= min(ans,s); return; } //剪枝 if (v + qv[cnt] > n) return; if (s + (n - v) / r > ans) return; for (int i = r - 1; i >= cnt; i--) { if (cnt == m) s = i * i; for (int j = h - 1; j >= cnt; j--) dfs(cnt - 1,2 * i * j + s,v + i * i * j,i,j); } } int main() { scanf("%d%d",&n,&m); for (int i = 1; i <= m; i++) { int t2 = i * i * i; qv[i] += qv[i-1] + t2; } dfs(m,0,0,sqrt(n),n); if (ans != inf) printf("%d\n",ans); else printf("0\n"); return 0; }

 

noi1999 生日蛋糕