lightoj1044_区间dp
Posted _lm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lightoj1044_区间dp相关的知识,希望对你有一定的参考价值。
题目链接:http://lightoj.com/volume_showproblem.php?problem=1044
题意: n<=1000少度的字符串,最少能分别成几个回文子串
题解: dp[i][j]表示子串i~j的最小划分回文子串,则答案为dp[0][n-1];
预先n^2处理出所有回文区间,然后进行状态的转移;
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <ctime> 8 #include <queue> 9 #include <list> 10 #include <set> 11 #include <map> 12 using namespace std; 13 #define INF 0x3f3f3f3f 14 typedef long long LL; 15 16 char a[1005]; 17 int dp[1005][1005], vis[1005][1005]; 18 int dfs(int l, int r) 19 { 20 if(dp[l][r] != INF) 21 return dp[l][r]; 22 if(l == r) 23 return 1; 24 if(l > r) 25 return 0; 26 int sum = INF; 27 for(int i = l; i <= r; i++) 28 { 29 if(vis[l][i]) 30 sum = min(sum, 1 + dfs(i+1, r)); 31 } 32 sum = min(sum, dfs(l+1, r)+1); 33 dp[l][r] = sum; 34 return sum; 35 } 36 int main() 37 { 38 int t; 39 scanf("%d", &t); 40 for(int ca = 1; ca <= t; ca++) 41 { 42 scanf("%s", a); 43 memset(dp, INF, sizeof(dp)); 44 memset(vis, 0, sizeof(vis)); 45 int len = strlen(a); 46 for(int i = 0; i < len; i++) 47 { 48 vis[i][i] = 1; 49 for(int l = i-1, r = i+1; l >= 0 && r < len; l--, r++) 50 { 51 if(a[l] == a[r]) 52 vis[l][r] = 1; 53 if(a[l] != a[r]) 54 break; 55 } 56 for(int l = i, r = i+1; l >= 0 && r < len; l--, r++) 57 { 58 if(a[l] == a[r]) 59 vis[l][r] = 1; 60 if(a[l] != a[r]) 61 break; 62 } 63 } 64 printf("Case %d: %d\n", ca, dfs(0, len-1)); 65 } 66 return 0; 67 }
以上是关于lightoj1044_区间dp的主要内容,如果未能解决你的问题,请参考以下文章
Light oj 1044 - Palindrome Partitioning(区间dp)
Palindrome Partitioning LightOJ - 1044(回文串最小分割数,O(n^2)预处理子串是否回文)