問題の説明
あなたの中には、「ブロック」と呼ばれるゲームをプレイしている可能性があります。行のn個のブロックがあり、各ボックスは色を有します。ここでは一例です:ゴールド、シルバー、シルバー、シルバー、シルバー、ブロンズ、ブロンズ、ブロンズ、ゴールド。
対応する画像は、以下のように示されます。
いくつかの隣接したボックスは、同じ色のすべて、およびその左にあるボックス(存在する場合)とその右の両方である場合には(存在する場合)、いくつかの他の色、私たちは「ボックス・セグメント」と呼んでいます。4箱のセグメントがあります。つまり:金、銀、青銅、金。それぞれのセグメントにおける1、4、3、1箱(ES)があります。
たびに、あなたはボックスをクリックすることができ、そのボックスを含む全セグメントが消えます。そのセグメントは、k個の箱で構成されている場合は、kを取得するk個のポイントを。銀のセグメントが消えたとえば、あなたがシルバーボックスをクリックした場合、あなたは4ました 4 = 16点を。
今度は下の画像を見てみましょう:
最初の1が最適です。
このゲームの初期状態を考えると、あなたが得ることができる最高のスコアを見つけます。
入力形式
最初の行は試験さt(1 <= T <= 15)の数を含んでいます。各ケースは2行が含まれています。最初の行は整数nを含有する(1 <= N <= 200)、ボックスの数。2行目は、各ボックスの色を表す、n個の整数を含みます。整数は範囲1〜Nです。
出力フォーマット
各テストケースのために、ケースの数と可能な限り最高のスコアを印刷します。
サンプル入力
2
9
1 2 2 2 2 3 3 3 1
1
1
サンプル出力
ケース1:29
事例2:1
問題の意味を総括
配列与えられ、それはすべての時間セグメントを除去することができる期間の長さがKである場合、k個の* kはスコアを取得する、要素の同じ種類です。利用可能な最大のポイントを探しています。
解決
明らかに、これは動的なプログラミングの問題の範囲である、あなたは、検索が達成する方法のメモリを使用することができます。まず、使用することができる\(1- \)と\(式中、R \)の範囲の間隔を表します。必要性が連続的に可変間隔の長さを測定するために、しかし、これだけでは、十分な状態遷移ではありません。私たちのブレークスルーは、サブインターバルのすべての州の独立性です。
サブ間隔で\([L、R] \) 、この区間にのみ二つの方法を排除したい:まず、Rと隣接する全て同じ色の正方形を除去し、その後インターバル除去\([Lを、R-1 ] \) ;第二のに見出される\([L、R] \ ) の位置に\(K \)になり\(R&LT \)と\(K \)同じ色の、間隔消去\([K + 1を、R-1] \)ように一緒に消去及び間隔を消去した後片と同じ色\([L ,. 1-K] \) 。この理論的根拠は、前述の独立性ということです。任意の間隔については、目標は、だけではなく、他のパイプ部分の、間隔を排除することです。間隔独立したサブ間隔の決定による内部間隔。これは、以下の式がゼロに見える説明しています。
要約すると、聞かせて([L] [R fは\を ] [k]が\) 間隔を表し(\ [L、R])を \ の右側に\(R&LTの\)同じ色のものである(K \)\時間ブロックを消去します部分最適解(同右を含む部分)。我々は、状態遷移方程式を取得することができる
:。\を[F [L] [R&LT] [K] = MAX(F [L] [R&LT-1] [0] +(K + 1)^ 2、F [L] [I -1] [K + 1] +
F [I + 1] [R-1] [0])\] ここで、\(L <= I <= R&LT、COL [I] = COL [R&LT] \)。必要性を供するために、我々はまた、第一の色フロントのそれぞれを記録し、同じ色を所有する必要があります。このアイデアは達成するために、隣接テーブルにグラフ理論上に描画することができます。
コード
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 202
using namespace std;
int t,n,i,a[N],f[N][N][N],nxt[N],head[N],cnt;
int dp(int l,int r,int k)
{
if(l>r) return 0;
if(f[l][r][k]!=0) return f[l][r][k];
f[l][r][k]=max(f[l][r][k],dp(l,r-1,0)+(k+1)*(k+1));
for(int i=nxt[r];i>=l;i=nxt[i]){
f[l][r][k]=max(f[l][r][k],dp(l,i,k+1)+dp(i+1,r-1,0));
}
return f[l][r][k];
}
int main()
{
cin>>t;
while(t--){
cnt++;
cin>>n;
memset(f,0,sizeof(f));
memset(head,0,sizeof(head));
memset(nxt,0,sizeof(nxt));
for(i=1;i<=n;i++){
cin>>a[i];
nxt[i]=head[a[i]];
head[a[i]]=i;
}
cout<<"Case "<<cnt<<": "<<dp(1,n,0)<<endl;
}
}