LightOJ 1044 Palindrome Partitioning(记忆化搜索)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1044

题意:给出一个字符串,问将字符串最少截成多少段可使每段都是一个回文串?

思路:预处理ok[i][j],表示[i,j]之间是不是回文串。然后记忆化搜索即可。。。我一开始没有预处理ok数组直接记忆化搜索的,TLE了半天。。。。

 

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #define min(x,y) ((x)<(y)?(x):(y))

 5 using namespace std;

 6 

 7 int C,num=0;

 8 int n,f[1005][1005],ok[1005][1005];

 9 char s[1005];

10 

11 

12 inline int DFS(int a,int b)

13 {

14     if(f[a][b]!=-1) return f[a][b];

15     if(ok[a][b]) return f[a][b]=1;

16     f[a][b]=b-a+1;

17     int i;

18     for(i=a;i<b;i++) if(ok[a][i]) f[a][b]=min(f[a][b],1+DFS(i+1,b));

19     return f[a][b];

20 }

21 

22 void init()

23 {

24     memset(ok,0,sizeof(ok));

25     int i,j,len;

26     for(i=0;i<n;i++) ok[i][i]=1;

27     for(i=0;i+1<n;i++) ok[i][i+1]=(s[i]==s[i+1]);

28     for(len=3;len<=n;len++) for(i=0;i+len<=n;i++)

29     {

30         j=i+len-1;

31         ok[i][j]=((s[i]==s[j])&&ok[i+1][j-1]);

32     }

33 }

34 

35 int main()

36 {

37     for(scanf("%d",&C);C--;)

38     {

39         scanf("%s",s);

40         n=strlen(s);

41         memset(f,-1,sizeof(f));

42         init();

43         printf("Case %d: %d\n",++num,DFS(0,n-1));

44     }

45     return 0;

46 }

你可能感兴趣的:(partition)