题目链接
区间 DP 的经典模型之一。
题意是将整个串通过四种操作变成一个回文串,根据套路,不难设计出 dp[i][j] 表示为使区间 [i, j] 成为回文串的最少操作次数。
先判断 a[i] 是否等于 a[j],如果相等,那么:
f[i][j] = max(f[i][j], f[i + 1][j - 1])
如果不相等,则改变一个:
f[i][j] = max(f[i][j], f[i + 1][j - 1] + 1)
其实可以发现第一、二种操作都和第三种等价,这三种转移可以表示为:
f[i][j] = max(f[i][j - 1], f[i + 1][j]) + 1
对于区间 DP,已经得到答案的区间我们都可以直接认为它是已满足题意要求的性质的,因为所记录的答案就是使其成立的最小代价。
然后设计方程乱搞,对于该模型就是考虑让区间两端点满足性质的问题……
1 #include <queue> 2 #include <cstdio> 3 #include <cctype> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 3000 + 10; 10 int n, a[maxn], dp[maxn][maxn]; 11 12 int main(int argc, char const *argv[]) 13 { 14 freopen("nanjolno.in", "r", stdin); 15 freopen("nanjolno.out", "w", stdout); 16 17 scanf("%d", &n); 18 for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); 19 for(int i = 2; i <= n; ++i) { 20 for(int l = 1; l + i - 1 <= n; ++l) { 21 int r = l + i - 1; 22 if( a[l] == a[r] ) dp[l][r] = dp[l + 1][r - 1]; 23 else dp[l][r] = min(dp[l + 1][r - 1], min(dp[l][r - 1], dp[l + 1][r])) + 1; 24 } 25 } 26 printf("%d\n", dp[1][n]); 27 28 fclose(stdin), fclose(stdout); 29 return 0; 30 }
—— 与漫长的人生相比,两人共处的时间仅一瞬间;
即使这些只是昙花一现的回忆,那时的我却以此为信仰。