$ [NOI1999] $の誕生日ケーキ

\(\ mathcal {説明} \)

7月17日である\(Mr.W \)誕生日、\(THU-ACM \)のボリュームを作成するには、この目的のために(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 = S \ PI \) プログラムに与えられた\(N \)\(M \) 、(ケーキレシピプログラムを見つけ、適切なために\(R_iと\)\(H_I \)の値)、そのように\(S \)最小。(ただし\(Q \) 上記のすべてのデータは、すべての正の整数です)

\(\ mathcal {入力\フォーマット} \)

二列、最初の行があり、\(N \) に作られるべきケーキの体積を表し(N \ PI \)を\は、第二行動\(M \) ケーキの層の数を表し\(M \)を

\(\ mathcal {出力\フォーマット} \)

一つだけの行は、正の整数である\(S \) 解がない場合\(S = 0 \) )。

\(\ mathcal {DATASIZE \契約} \)

\(1 \当量N \の当量20000、1 \当量のMの\の当量15 \)

\(\ mathcal {解決} \)

まず、検索を考えることは困難であり、直接検索は、いくつかの剪定を追加することを検討し、非常に遅くなります。

剪定の可能性:現在のレベルよりもプラス最小体積(\ \ N-)大は、不可能です。

最適なプルーニング:
1、プラスの領域での記録層よりも最小電流領域側\(ANS \)は意志が確かに最適ではないプログラムの種類、大きさである;
2、領域の下層側には、残りのボリュームに対応する場合加えて、現在の面積よりも小さくない\(ANS \) この解決策は最適ではない(なぜなら現在服用していないの次の層の半径に等しいより大きくなければならない\(R&LTを\)

各層の最小体積の前処理チップ、及び最小面積

\(\ mathcal {コード} \)

#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\n", (Ans == inf ? 0 : Ans));
  
  return 0;
}

おすすめ

転載: www.cnblogs.com/1miharu/p/11324527.html