状态转移。
如果clothes[i]==clothes[j]那么穿上第i件衣服之后不脱,在处理完[i+1,j-1]之后可以再使用这件衣服。所以dp[i][j]=dp[i+1][j-1]+1;
在某个区间之前或之后单独的穿一件衣服。
dp[i][j]=min(dp[i][j],dp[i+1][j]+1,dp[i][j-1]+1);
将一个区间分成两部分处理。那么中间的那件衣服可以用两次。
dp[i][j]=min(dp[i][k]+dp[k][j]-1)
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[102][102];
int main(){
int T, N, Case = 1;
int id[102];
cin >> T;
while( T-- ){
cin >> N;
for( int i = 1; i <= N; i++ ){
cin >> id[i];
}
memset( dp, 0, sizeof( dp ) );
for( int i = 1; i <= N; i++ ){
dp[i][i] = 1;
}
for( int l = 1; l <= N - 1; l++ ){
for( int i = 1; i + l <= N; i++ ){
int j = i + l;
dp[i][j] = min( dp[i][j-1] + 1, dp[i+1][j] +1 );
if( id[i] == id[j] ){
dp[i][j] = min( dp[i+1][j-1] + 1, dp[i][j] );
}
for( int k = i + 1; k < j; k++ ){
dp[i][j] = min( dp[i][k] + dp[k][j] - 1, dp[i][j] );
}
}
}
cout << "Case " << Case++ << ": " << dp[1][N] << endl;
}
return 0;
}