DFS(剪枝) - POJ 1190 - NOI1999 生日蛋糕

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 1N10000,1M20

输入样例:

100
2

输出样例:

68

分析:

目标: 给 定 总 体 积 为 N , 总 层 数 为 M 的 蛋 糕 , 求 表 面 积 的 最 小 值 ( 除 下 底 面 ) 。 给定总体积为N,总层数为M的蛋糕,求表面积的最小值(除下底面)。 NM()

半 径 为 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。 RuHuSu=2πRuHuVu=π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=2RuHuVu=Ru2Hu

我 们 自 顶 向 下 给 每 一 层 编 号 为 1 , 2 , . . . , M 。 我们自顶向下给每一层编号为1,2,...,M。 12...M

根 据 R 和 H 的 递 增 关 系 , d f s 枚 举 每 一 层 的 R 和 H 的 值 , 判 断 M 层 蛋 糕 体 积 是 否 恰 好 为 N , 求 合 法 方 案 中 表 面 积 的 最 小 值 。 根据R和H的递增关系,dfs枚举每一层的R和H的值,\\判断M层蛋糕体积是否恰好为N,求合法方案中表面积的最小值。 RHdfsRHMN

剪枝:

① 、 最 底 层 的 蛋 糕 半 径 最 大 , 体 积 最 大 , 能 够 减 少 枚 举 体 积 的 分 支 , 因 此 我 们 自 底 向 上 搜 索 。 由 于 R 对 体 积 的 影 响 要 大 于 H , 所 以 我 们 优 先 枚 举 R 。 ①、最底层的蛋糕半径最大,体积最大,能够减少枚举体积的分支,因此我们自底向上搜索。\\\qquad由于R对体积的影响要大于H,所以我们优先枚举R。 RHR

② 、 由 于 自 顶 向 下 每 一 层 的 半 径 和 高 是 递 增 的 , 且 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 RHuuRuRu+11uHuHu+11

假 设 第 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}。 uvNv NvRu2HuRu2RuNv

同 理 由 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}。 NvRu2HuHuRu2Nv

综 上 : 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})。 uRumin(Ru+11,Nv )uHumin(Hu+11,Ru2Nv)

③ 、 预 处 理 出 前 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是当前已经枚举到的合法方案的表面积的最小值。 uminv[u]mins[u]uVuSu Vu+minv[u]NSu+mins[u]<ansans

预 处 理 方 案 就 是 半 径 按 照 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,...,MRu=Hu=uu[1,M]

可 见 , 对 V u 是 可 行 性 剪 枝 , 对 S u 是 最 优 性 剪 枝 。 \qquad 可见,对V_u是可行性剪枝,对S_u是最优性剪枝。 VuSu

④ 、 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。 1uS1u=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。 uvNv=V1u=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}。 S1u=i=1u2RiHi=2i=1uRiHiRi+1Ri+11=Ri+12i=1uRiHiRi+1Ri+12i=1uRi2Hi=Ri+12V1u

即 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}}。 S1u>Ri+12V1u=Ri+12(Nv)

因 此 , 设 第 u 层 以 下 已 经 枚 举 过 的 蛋 糕 总 的 表 面 积 为 s , 若 s + 2 ( N − v ) R i + 1 ≥ a n s , 说 明 该 分 支 不 能 更 新 最 优 解 。 \qquad 因此,设第u层以下已经枚举过的蛋糕总的表面积为s,若s+\frac{2(N-v)}{R_{i+1}}≥ans,说明该分支不能更新最优解。 uss+Ri+12(Nv)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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值