Light OJ 1422-ハロウィンCostumes
5200 ワード
テーマリンク:http://lightoj.com/volume_showproblem.php?problem=1422
とても簡単な区間DPの入門問題です.最初はこの問題を長い間考えましたが、思い出せませんでした.後のいくつかの区間DPをして戻ってきたらやっと分かりました.
区間DPは、記憶化探索および直接DPの方法を用いて書くことができる.
この問題の状態は方程式を変えます.
dp[i][j]=min(1+dp[i+1][j],dp[i+1][k-1]+dp[k][j] ( a[i]==a[k] i初期化に注意します
とても簡単な区間DPの入門問題です.最初はこの問題を長い間考えましたが、思い出せませんでした.後のいくつかの区間DPをして戻ってきたらやっと分かりました.
区間DPは、記憶化探索および直接DPの方法を用いて書くことができる.
この問題の状態は方程式を変えます.
dp[i][j]=min(1+dp[i+1][j],dp[i+1][k-1]+dp[k][j] ( a[i]==a[k] i
/*
* Light OJ 1422 - Halloween Costumes
* http://lightoj.com/volume_showproblem.php?problem=1422
* DP 。
* i j,dp[i][j].
* i , i i , dp[i+1][j]+1
* i+1~j k, a[i]==a[k]. dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k][j])
* i , 1, dp[k][j]
*
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXN=110;
int a[MAXN];
int dp[MAXN][MAXN];
int main()
{
int T;
int n;
scanf("%d",&T);
int iCase=0;
while(T--)
{
iCase++;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
dp[i][j]=j-i+1;
for(int i=n-1;i>=1;i--)// DP
for(int j=i+1;j<=n;j++)
{
dp[i][j]=dp[i+1][j]+1;// i
for(int k=i;k<=j;k++)
if(a[i]==a[k])//
dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k][j]);
}
printf("Case %d: %d
",iCase,dp[1][n]);
}
return 0;
}