题目链接:
Lightoj 1025 - The Specials Menu
题目描述:
给出一个字符串,可以任意删除位置的字符,也可以删除任意多个。问能组成多少个回文串?
解题思路:
自从开始学dp,感觉自己智商一直处于离线状态。席八啊啊啊啊啊啊!今天随机到这个题目,看了好久竟然没有看出来是区间DP。知道是区间DP后立马感觉明白。
情景设定 dp[l][r] 表示 区间 [l, r] 内的回文串数目。
状态转移:dp[l][r] = dp[l][r-1] + dp[l+1][r], 但是这样会加重复的,所以要减去dp[l+1][r-1], 当a[l] == a[r]的时候,对于区间[l, r]之间的回文串,就可以变成以a[l]与a[r]结尾的,然后就需要加上。
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 7 using namespace std; 8 typedef long long LL; 9 const int maxn = 70; 10 const int INF = 0x3f3f3f3f; 11 LL dp[maxn][maxn]; 12 char a[maxn]; 13 14 int main () 15 { 16 int T; 17 scanf ("%d", &T); 18 for (int t=1; t<=T; t++) 19 { 20 scanf ("%s", a+1); 21 int len = strlen (a+1); 22 memset (dp, 0, sizeof(dp)); 23 24 for (int i=1; i<=len; i++) 25 for (int l=1; l+i-1<=len; l++) 26 { 27 int r = l + i - 1; 28 dp[l][r] += dp[l+1][r]; 29 dp[l][r] += dp[l][r-1]; 30 31 if (a[l] == a[r]) dp[l][r] += 1; 32 else dp[l][r] -= dp[l+1][r-1]; 33 34 } 35 printf ("Case %d: %lld ", t, dp[1][len]); 36 } 37 return 0; 38 }