最大の[LuoGu] P1018製品

\(\色{赤} {\ mathcal {説明}} \)

今年は、「決定するために国際数学連合です\(2000 \)も、---世界数理年」の有名な数学者、氏は華の誕生日と一致している\(90 \)周年。氏は華の故郷ジンタン、数学のクイズは、あなたの友人の、壮大な1の活動を組織し、\(XZ \)も参加する機会を持っています。活動は、すべてのプレイヤーのホストは、この一人の被験者のうち、活動に参加します:

長さがある\(N \)数字の文字列を、プレイヤーが使用が必要です\(K \)それはに乗算番目の\(K + 1 \)のポイントを見つけるために、部品、そのので\(K +1 \)生成物の一部を最大にすることができます。

次のように一方、プレイヤーが正しく質問の意味を理解することができるよう支援するために、司会者も例を引用しました:

数字列:\(312 \) \(N = 3 \) \(K = 1 \。)二つのタイムポイントシステムがあります。

\(\ = 12 3回36 \である。) (\ 31 \ 2 = 62であるタイムズ\である)この場合、結果は、被験体の要件に沿ったものである:\(31 \ 2 = 62であるタイムズ\です)

さて、あなたはあなたの友人を助ける\(XZ \)正しい答えを得るためにプログラムを設計します。

\(\色{赤} {\ mathcal {入力\形式}} \)

入力プログラムの二列:最初の行は、22点の自然数有している\(N、K \)を、2行目は長さである\(N \)数値文字列。

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

結果は、入力の最大積に対して、画面に表示され、出力は、(自然数)を取得しなければなりません。

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

\(6≤N≤40,1≤K≤6\)

\(\色{赤} {\ mathcal {解決}} \)

リニアDP

注文\(DP [i]の[jは ] \) 前回表し\(私は\)文字を挿入\(J \)の列挙を取得するために最大の乗算積番目の\(J \)を挿入乗算目を位置(\(K \)の数字の後)が、伝達方程式が得られます。

\ [DP [I] [J] = \最大{DP [K] [J-1] * NUM(K + 1、i)は} \ \ \ \ \ \(iは当量Nを\ 2 \当量、1 \当量J \当量\分(I-1、K)、J \当量のK <I)\]

初期化\(DP [I] [0 ] = NUM iの当量のNを\(1、I)\ \ \(1つの\ 1当量)\)

\(\色{赤} {\ mathcal {コード}} \)

#include <bits/stdc++.h>
#define LL long long
#define reg register

using namespace std;

const int kN = 100;

LL dp[kN][kN];
string num;
int N, K; 

LL Cut(int l, int r) {
  LL ret = 0;
  for (reg int i = l; i <= r; ++i)
    ret = ret * 10 + num[i - 1] - '0';
  return ret;
}

int main() {
  scanf("%d%d", &N, &K);
  cin >> num;
  for (reg int i = 1; i <= N; ++i)
    dp[i][0] = dp[i - 1][0] * 10 + num[i - 1] - '0';
  for (reg int i = 2; i <= N; ++i)
    for (reg int j = 1; j <= min(i - 1, K); ++j)
      for (reg int k = j; k < i; ++k)
        dp[i][j] = max(dp[i][j], dp[k][j - 1] * Cut(k + 1, i));
  printf("%lld\n", dp[N][K]);
  return 0;
}

おすすめ

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