DFS(剪枝) - POJ 1190 - NOI1999 生日蛋糕
7月17日是 Mr.W 的生日,ACM-THU 为此要制作一个体积为 N π Nπ Nπ 的 M 层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i层蛋糕是半径为 R i R_i Ri, 高度为 H i H_i Hi的圆柱。
当 i < M 时,要求 R i > R i + 1 R_i > R_{i+1} Ri>Ri+1且 H i > H i + 1 H_i > H_{i+1} Hi>Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 Q 最小。
令 Q = S π Q = Sπ Q=Sπ ,请编程对给出的 N 和 M ,找出蛋糕的制作方案(适当的 R i R_i Ri和 H i H_i Hi的值),使 S 最小。
除 Q 外,以上所有数据皆为正整数 。
输入格式
输入包含两行,第一行为整数 N(N <= 10000),表示待制作的蛋糕的体积为
N
π
Nπ
Nπ。
第二行为整数 M (M <= 20) ,表示蛋糕的层数为 M。
输出格式
输出仅一行,是一个正整数 S(若无解则S = 0)。
数据范围
1
≤
N
≤
10000
,
1
≤
M
≤
20
1≤N≤10000, 1≤M≤20
1≤N≤10000,1≤M≤20
输入样例:
100
2
输出样例:
68
分析:
目标: 给 定 总 体 积 为 N , 总 层 数 为 M 的 蛋 糕 , 求 表 面 积 的 最 小 值 ( 除 下 底 面 ) 。 给定总体积为N,总层数为M的蛋糕,求表面积的最小值(除下底面)。 给定总体积为N,总层数为M的蛋糕,求表面积的最小值(除下底面)。
半 径 为 R u , 高 为 H u 的 圆 柱 侧 面 积 : S u = 2 π R u H u ; 体 积 V u = π R u 2 H u 。 半径为R_u,高为H_u的圆柱侧面积:S_u=2\pi R_uH_u;体积V_u=\pi R_u^2H_u。 半径为Ru,高为Hu的圆柱侧面积:Su=2πRuHu;体积Vu=πRu2Hu。
本 题 不 考 虑 π , S u = 2 R u H u ; 体 积 V u = R u 2 H u 。 本题不考虑\pi ,S_u=2R_uH_u;体积V_u=R_u^2H_u。 本题不考虑π,Su=2RuHu;体积Vu=Ru2Hu。
我 们 自 顶 向 下 给 每 一 层 编 号 为 1 , 2 , . . . , M 。 我们自顶向下给每一层编号为1,2,...,M。 我们自顶向下给每一层编号为1,2,...,M。
根 据 R 和 H 的 递 增 关 系 , d f s 枚 举 每 一 层 的 R 和 H 的 值 , 判 断 M 层 蛋 糕 体 积 是 否 恰 好 为 N , 求 合 法 方 案 中 表 面 积 的 最 小 值 。 根据R和H的递增关系,dfs枚举每一层的R和H的值,\\判断M层蛋糕体积是否恰好为N,求合法方案中表面积的最小值。 根据R和H的递增关系,dfs枚举每一层的R和H的值,判断M层蛋糕体积是否恰好为N,求合法方案中表面积的最小值。
剪枝:
① 、 最 底 层 的 蛋 糕 半 径 最 大 , 体 积 最 大 , 能 够 减 少 枚 举 体 积 的 分 支 , 因 此 我 们 自 底 向 上 搜 索 。 由 于 R 对 体 积 的 影 响 要 大 于 H , 所 以 我 们 优 先 枚 举 R 。 ①、最底层的蛋糕半径最大,体积最大,能够减少枚举体积的分支,因此我们自底向上搜索。\\\qquad由于R对体积的影响要大于H,所以我们优先枚举R。 ①、最底层的蛋糕半径最大,体积最大,能够减少枚举体积的分支,因此我们自底向上搜索。由于R对体积的影响要大于H,所以我们优先枚举R。
② 、 由 于 自 顶 向 下 每 一 层 的 半 径 和 高 是 递 增 的 , 且 R 和 H 是 整 数 , 故 对 第 u 层 圆 柱 , 有 不 等 关 系 : u ≤ R u ≤ R u + 1 − 1 u ≤ H u ≤ H u + 1 − 1 ②、由于自顶向下每一层的半径和高是递增的,且R和H是整数,故对第u层圆柱,有不等关系:\\\qquad u≤R_u≤R_{u+1}-1\\\qquad u≤H_u≤H_{u+1}-1 ②、由于自顶向下每一层的半径和高是递增的,且R和H是整数,故对第u层圆柱,有不等关系:u≤Ru≤Ru+1−1u≤Hu≤Hu+1−1
假 设 第 u 层 以 下 的 蛋 糕 总 体 积 为 v , 则 剩 下 的 体 积 总 量 为 N − v , 则 有 N − v ≥ R u 2 H u ≥ R u 2 , 得 到 R u ≤ N − v 。 \qquad 假设第u层以下的蛋糕总体积为v,则剩下的体积总量为N-v,\\ \ \\\qquad则有N-v≥R_u^2H_u≥R_u^2,得到R_u≤\sqrt{N-v}。 假设第u层以下的蛋糕总体积为v,则剩下的体积总量为N−v, 则有N−v≥Ru2Hu≥Ru2,得到Ru≤N−v。
同 理 由 N − v ≥ R u 2 H u , 得 到 H u ≤ N − v R u 2 。 \qquad 同理由N-v≥R_u^2H_u,得到H_u≤\frac{N-v}{R_u^2}。 同理由N−v≥Ru2Hu,得到Hu≤Ru2N−v。
综 上 : u ≤ R u ≤ m i n ( R u + 1 − 1 , N − v ) , u ≤ H u ≤ m i n ( H u + 1 − 1 , N − v R u 2 ) 。 \qquad 综上:u≤R_u≤min(R_{u+1}-1,\sqrt{N-v}),u≤H_u≤min(H_{u+1}-1,\frac{N-v}{R_u^2})。 综上:u≤Ru≤min(Ru+1−1,N−v),u≤Hu≤min(Hu+1−1,Ru2N−v)。
③ 、 预 处 理 出 前 u 层 体 积 最 小 值 m i n v [ u ] 和 m i n s [ u ] 。 则 对 第 u 层 蛋 糕 的 体 积 V u 和 表 面 积 S u , 有 V u + m i n v [ u ] ≤ N , S u + m i n s [ u ] < a n s 。 其 中 a n s 是 当 前 已 经 枚 举 到 的 合 法 方 案 的 表 面 积 的 最 小 值 。 ③、预处理出前u层体积最小值minv[u]和mins[u]。则对第u层蛋糕的体积V_u和表面积S_u,有\\ \ \\\qquad V_u+minv[u]≤N,S_u+mins[u]<ans。其中ans是当前已经枚举到的合法方案的表面积的最小值。 ③、预处理出前u层体积最小值minv[u]和mins[u]。则对第u层蛋糕的体积Vu和表面积Su,有 Vu+minv[u]≤N,Su+mins[u]<ans。其中ans是当前已经枚举到的合法方案的表面积的最小值。
预 处 理 方 案 就 是 半 径 按 照 1 , 2 , . . . , M 递 增 , 即 R u = H u = u , u ∈ [ 1 , M ] 。 \qquad 预处理方案就是半径按照1,2,...,M递增,即R_u=H_u=u,u∈[1,M]。 预处理方案就是半径按照1,2,...,M递增,即Ru=Hu=u,u∈[1,M]。
可 见 , 对 V u 是 可 行 性 剪 枝 , 对 S u 是 最 优 性 剪 枝 。 \qquad 可见,对V_u是可行性剪枝,对S_u是最优性剪枝。 可见,对Vu是可行性剪枝,对Su是最优性剪枝。
④ 、 1 到 u 层 的 表 面 积 之 和 S 1 − u = ∑ i = 1 u 2 R i H i 。 ④、1到u层的表面积之和S_{1-u}=\sum_{i=1}^{u}2R_iH_i。 ④、1到u层的表面积之和S1−u=∑i=1u2RiHi。
由 于 我 们 是 自 底 向 上 枚 举 , 设 第 u 层 以 下 已 经 枚 举 过 的 蛋 糕 总 体 积 为 v , 则 N − v = V 1 − u = ∑ i = 1 u R i 2 H i 。 \qquad 由于我们是自底向上枚举,设第u层以下已经枚举过的蛋糕总体积为v,则N-v=V_{1-u}=\sum_{i=1}^{u}R_i^2H_i。 由于我们是自底向上枚举,设第u层以下已经枚举过的蛋糕总体积为v,则N−v=V1−u=∑i=1uRi2Hi。
则 有 S 1 − u = ∑ i = 1 u 2 R i H i = 2 ∑ i = 1 u R i H i R i + 1 ⋅ 1 R i + 1 = 2 R i + 1 ∑ i = 1 u R i H i R i + 1 > 2 R i + 1 ∑ i = 1 u R i 2 H i = 2 R i + 1 V 1 − u 。 \qquad 则有S_{1-u}=\sum_{i=1}^{u}2R_iH_i=2\sum_{i=1}^{u}R_iH_iR_{i+1}·\frac{1}{R_{i+1}}=\frac{2}{R_{i+1}}\sum_{i=1}^{u}R_iH_iR_{i+1}>\frac{2}{R_{i+1}}\sum_{i=1}^{u}R_i^2H_i=\frac{2}{R_{i+1}}V_{1-u}。 则有S1−u=∑i=1u2RiHi=2∑i=1uRiHiRi+1⋅Ri+11=Ri+12∑i=1uRiHiRi+1>Ri+12∑i=1uRi2Hi=Ri+12V1−u。
即 S 1 − u > 2 R i + 1 V 1 − u = 2 ( N − v ) R i + 1 。 \qquad 即S_{1-u}>\frac{2}{R_{i+1}}V_{1-u}=\frac{2(N-v)}{R_{i+1}}。 即S1−u>Ri+12V1−u=Ri+12(N−v)。
因 此 , 设 第 u 层 以 下 已 经 枚 举 过 的 蛋 糕 总 的 表 面 积 为 s , 若 s + 2 ( N − v ) R i + 1 ≥ a n s , 说 明 该 分 支 不 能 更 新 最 优 解 。 \qquad 因此,设第u层以下已经枚举过的蛋糕总的表面积为s,若s+\frac{2(N-v)}{R_{i+1}}≥ans,说明该分支不能更新最优解。 因此,设第u层以下已经枚举过的蛋糕总的表面积为s,若s+Ri+12(N−v)≥ans,说明该分支不能更新最优解。
其 中 a n s 是 当 前 已 经 枚 举 到 的 合 法 方 案 的 表 面 积 的 最 小 值 。 这 里 仍 然 是 最 优 性 剪 枝 。 \qquad 其中ans是当前已经枚举到的合法方案的表面积的最小值。这里仍然是最优性剪枝。 其中ans是当前已经枚举到的合法方案的表面积的最小值。这里仍然是最优性剪枝。
代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=25,inf=1e9;
int n,m;
int minv[N],mins[N];
int R[N],H[N];
int ans=inf;
void dfs(int u,int v,int s)
{
if(v + minv[u] > n) return; //可行性剪枝
if(s + mins[u] >= ans) return; //最优性剪枝
if(s + 2*(n-v)/R[u+1] >= ans) return; //最优性剪枝
if(u==0) //到顶
{
if(v==n) ans=s;
return;
}
for(int r = min(R[u+1]-1,(int)sqrt(n-v)); r >= u; r--) //从大到小枚举
for(int h = min(H[u+1]-1,(n-v)/r/r); h >= u; h--)
{
int tmp=0;
if(u==m) tmp=r*r; //最底层先加上上表面面积
R[u]=r,H[u]=h;
dfs(u-1,v+r*r*h,s+2*r*h+tmp);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
minv[i]=minv[i-1]+i*i*i;
mins[i]=mins[i-1]+2*i*i;
}
R[m+1]=H[m+1]=inf; //最后一层要用到下一层的参数,故初始化边界为inf
dfs(m,0,0);
if(ans==inf) ans=0; //无解输出0
cout<<ans<<endl;
return 0;
}