P1880 [NOI1995]合成砂利
タイトル説明
円形の石の周りの遊び場は、新しいパイル及び石の新しい山に石パイルにマージするために有することである。各時間だけ所定の選択された隣接スタック2、Nを配置積ま番号、複合スコアことを覚えておいてください。
テストスタック最小複合スコアと最大スコアに重ねN石を計算するアルゴリズムを設計します。
入力形式
第1データ線試験の正の整数N、1≤N≤100、N石が発現重ね。第二行は、それぞれ、数Nを有し、石の各山の数を表します。
出力フォーマット
出力コモンライン2、ライン1は、最小スコア、2行目の最大スコアです。
サンプル入力と出力
入力#1
4
4 5 8 4
出力#1
43
54
[思考]
DPの範囲
[コア]アイデア
円である
ので、明らかなアプローチは
、それが背後に元のシーケンスと元のシーケンスとして配列を置くことである
ようなセクション2-N + 1が発生している
と1-nは番号が
異なるだけ始めています
組み合わせた元の値に組み合わせた値が等しいたびに
プラス
いくつかの石の合併は、
[I] [J] Fのみ2次元配列は、その後、明らかに保存された方法がない場合
、あなたは非常に美しいもののを利用することができるように
接頭辞と
これは、プレフィックスと範囲に石の数を用いて計算することができ
合併は新しい値を得ることができ、すべての石を知ることができる
、あなただけIJ区間内に維持するために[I] [J] fを使用することができます
うまく統合石のための最高の価値
式[DP]
DP式:
F1 [I] [J] = MAX(F1 [I]、[J]、F1 [I] [K] + F1 [K + 1] [J] +コスト[I] [J])
F2 [I ] [J]が分(F2 [I]、[J]、F2 [I] [K] + F2 [K + 1] [J] +コスト[I] [J])=
(要求間隔の最大値を求めます最小間隔)
この間隔は、マージされた二つの間のほとんどの細胞後の値に最良の値に等しいです。
【最終結果】
最後に、結果は、
1本間隔それ-自然に比較II + nは、
環が1行とは異なるので、原点を任意にすることができ
たときに出発点として最も値のそれぞれと比較するように
出力のような
[完了コード】
#include<iostream>
#include<cstdio>
using namespace std;
const int Max = 206;
int f1[Max][Max];
int f2[Max][Max];
int a[Max];
int sum[Max];
int cost[Max][Max];
int main()
{
int n;
cin >> n;
for(register int i = 1;i <= n;++ i)
cin >> a[i],a[i + n] = a[i];
for(register int i = 1;i <= n * 2;++ i)
sum[i] = sum[i - 1] + a[i];
for(register int i = 1;i <= n * 2;++ i)
for(register int j = i;j <= n * 2;++ j)
cost[i][j] = sum[j] - sum[i - 1];
for(register int len = 1;len <= n;++ len)
{
for(register int i = 1;i + len - 1 <= n * 2;++ i)
{
int j = i + len - 1;
if(i != j)
f2[i][j] = 999999999;
for(register int k = i;k < j;++ k)
f1[i][j] = max(f1[i][j],f1[i][k] + f1[k + 1][j] + cost[i][j]),
f2[i][j] = min(f2[i][j],f2[i][k] + f2[k + 1][j] + cost[i][j]);
}
}
int M = 0;
int MM = 0x7fffffff;
for(register int i = 1;i <= n;++ i)
M = max(M,f1[i][i + n - 1]),
MM = min(MM,f2[i][i + n - 1]);
cout << MM << endl << M << endl;
return 0;
}