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 }

 

posted @ 2016-10-06 19:04  海无泪  阅读(140)  评论(0编辑  收藏  举报