zoukankan      html  css  js  c++  java
  • [LuoGu] P1731 生日蛋糕

    (color{red}{mathcal{Description}})

    7月17日是 (Mr.W) 的生日,(ACM-THU) 为此要制作一个体积为的 (M) 层生日蛋糕,每层都是一个圆柱体。设从下往上数第 (i) ((1 leq i leq M)) 层蛋糕是半径为 (R_i) , 高度为 (H_i) 的圆柱。当 (i<M) 时,要求 (R_i>R_{i+1})(H_i>H_{i+1}) 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 (Q) 最小。令 (Q = Spi) ,请编程对给出的 (N)(M) ,找出蛋糕的制作方案(适当的 (R_i)(H_i) 的值),使 (S) 最小。(除 (Q) 外,以上所有数据皆为正整数)

    (color{red}{mathcal{Input Format}})

    有两行,第一行为 (N) ,表示待制作的蛋糕的体积为 (Npi);第二行为 (M),表示蛋糕的层数为 (M)

    (color{red}{mathcal{Output Format}})

    仅一行,是一个正整数 (S)(若无解则 (S=0))。

    (color{red}{mathcal{DataSize Agreement}})

    (1 leq N leq 20000 , 1 leq M leq 15).

    (color{red}{mathcal{Hint}})

    圆柱相关公式:(V=pi R^2H)体积 ;侧面积 (S'=2 pi RH);底面积 (S=pi R^2)

    (color{red}{mathcal{Solution}})

    首先不难想到的是搜索,但直接搜索会很慢,考虑到要加一些剪枝:

    可行性剪枝:当前体积加上下一层最小的体积也比 (n) 大,不可行;

    最优性剪枝:
    1、当前面积加上下一层的最小侧面积比记录的 (ans) 大,那么该种方案定然不是最优的;
    2、如果剩余体积对应的下一层侧面积加上当前面积大于等于 (ans) ,该方案不是最优的(必须是大于等于因为下一层的半径取不到当前的 (r)

    一个小技巧是预处理出每一层的最小体积以及最小面积

    (color{red}{mathcal{Code}})

    #include <bits/stdc++.h>
    #define LL long long
    #define reg register
    
    using namespace std;
    
    const int kMax = 21;
    const int inf = 0x7f7f7f7f;
    
    int mins[kMax], minv[kMax];
    int N, M, Ans = inf;
    
    void dfs(int v, int s, int p, int r, int h) {
      if (p == 0) {
      	if (v == N) Ans = min(Ans, s);
    	return ;
      }
      if (v + minv[p - 1] > N) return ; // 可行性剪枝 
      if (s + mins[p - 1] > Ans) return ;  // 最优性剪枝
      if (s + (N - v) / r * 2 >= Ans) return ; //最优性剪枝
      for (reg int i = r - 1; i >= p; --i) {
      	if (p == M) s = i * i;
      	int minh = min(h - 1, (N - v - minv[p - 1]) / (i * i));
      	for (reg int j = minh; j >= p; --j)
      	  dfs(v + i * i * j, s + 2 * i * j, p - 1, i, j);
      }
    }
    
    int main() {
      scanf("%d%d", &N, &M);
      for (reg int i = 1; i <= 20; ++i) mins[i] = mins[i - 1] + i * i, minv[i] = minv[i - 1] + i * i * i;
      dfs(0, 0, M, N + 1, N + 1);
      printf("%d
    ", (Ans == inf ? 0 : Ans));
      
      return 0;
    }
    
    

    (color{red}{mathcal{Source}})

    (NOI 1999)

  • 相关阅读:
    ADO.NET 数据连接查询
    弹出消息对话框类
    C# 火星文转化 算法 dictionary 的使用案例
    微软官方的SqlHelper
    jsHelper
    【VC++积累】之六、MFC简要剖析
    C# 统计文章中字符的种类和个数 哈希表和字典的使用
    C# NetHelper
    C# XML操作类 XmlHelper
    【VS++积累】之七、黑客编程之匿名管道
  • 原文地址:https://www.cnblogs.com/1miharu/p/11324527.html
Copyright © 2011-2022 走看看