题面翻译
Genos \texttt{Genos} Genos 最近在他的手机上下载了祖玛游戏。在祖玛游戏里,存在 n ( 1 ≤ n ≤ 500 ) n(1\leq n\leq 500) n(1≤n≤500) 个一行的宝石,第 i i i 个宝石的颜色是 C i C_i Ci。这个游戏的目标是尽快的消灭一行中所有的宝石。
在一秒钟, Genos \texttt{Genos} Genos 能很快的挑选出这些有颜色的宝石中的一个回文的、连续的子串,并将这个子串移除。每当一个子串被删除后,剩余的宝石将连接在一起,形成一个新的行列。
你的任务是:求出把整个宝石串都移除的最短时间。
思路
考虑区间 dp。
记 d p l , r dp_{l,r} dpl,r 为从 l l l 消除到 r r r 的最短时间,则:
d p i , i = 1 dp_{i,i} = 1 dpi,i=1
{ d p i , i + 1 = 1 , c i = c i + 1 d p i , i + 1 = 2 , o t h e r w i s e \begin{cases}dp_{i,i+1}=1,c_i=c_{i+1} \\dp_{i,i+1}=2,otherwise\end{cases} {dpi,i+1=1,ci=ci+1dpi,i+1=2,otherwise
对于 r − l ≥ 2 r-l \geq 2 r−l≥2时,考虑转移,容易想到 d p l , r dp_{l,r} dpl,r 可由 d p l + 1 , r − 1 dp_{l + 1,r-1} dpl+1,r−1 转移而来:
{ d p l , r = d p l + 1 , r − 1 , c l = c r d p l , r = d p l + 1 , r − 1 + 1 , o t h e r w i s e \begin{cases}dp_{l,r}=dp_{l+1,r - 1},c_l=c_r\\dp_{l,r}=dp_{l+1,r-1}+1, otherwise\end{cases} {dpl,r=dpl+1,r−1,cl=crdpl,r=dpl+1,r−1+1,otherwise
注意到 4 4 2 3 2
这个例子(样例 3),可以发现 d p 1 , 5 dp_{1,5} dp1,5 可以由 d p 1 , 2 + d p 3 , 5 dp_{1,2} + dp_{3,5} dp1,2+dp3,5 转移而来。综上所述:
d p l , r = m i n ( d p l , r , min j = l r ( d p l , j + d p j + 1 , r ) ) dp_{l,r} = min(dp_{l,r},\min_{j=l}^{r}{(dp_{l,j}+dp_{j+1,r})}) dpl,r=min(dpl,r,j=lminr(dpl,j+dpj+1,r))
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,c[505],dp[505][505];
signed main() {scanf("%lld",&n);for(int i = 1;i <= n;i++) scanf("%lld",&c[i]),dp[i][i] = 1;for(int i = 1;i < n;i++) {if(c[i] == c[i + 1]) dp[i][i + 1] = 1;else dp[i][i + 1] = 2;}for(int i = 2;i <= n;i++) {for(int l = 1;l + i - 1 <= n;l++) {int r = l + i - 1;if(c[l] == c[r]) dp[l][r] = dp[l + 1][r - 1];else {dp[l][r] = min(dp[l + 1][r],dp[l][r - 1]) + 1;}for(int j = l;j <= r;j++) dp[l][r] = min(dp[l][r],dp[l][j] + dp[j + 1][r]);//printf("(%lld,%lld)%lld ",l,r,dp[l][r]);}//printf("\n");} printf("%lld\n",dp[1][n]);return 0;
}