lightoj 1044 - Palindrome Partitioning(需要优化的区间dp)

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

题意:求给出的字符串最少能分成多少串回文串。

一般会想到用区间dp暴力3个for但是这里的数据有1000,3个for肯定超时的。

但是这题只是判断回文串有多少个所以可以先预处理一下[i,j]是不是回文,然后

就是简单dp了

for(int i = 1 ; i <= len ; i++) {

            ans[i] = ans[i - 1] + 1;

            for(int j = i - 1 ; j >= 1 ; j--) {

                if(dp[j][i]) {

                    ans[i] = min(ans[i] , ans[j - 1] + 1);//如果[i,j]是回文那么就是ans[j-1]+1

                }

            }

        }

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int dp[1010][1010] , ans[1010];
char s[1010];
int main() {
    int t , cnt = 0;
    scanf("%d" , &t);
    while(t--) {
        cnt++;
        scanf("%s" , s + 1);
        int len = strlen(s + 1);
        memset(dp , 0 , sizeof(dp));
        memset(ans , 0 , sizeof(ans));
        for(int k = 0 ; k <= len ; k++) {
            for(int l = 1 ; l <= len && l + k <= len ; l++) {
                int r = l + k;
                if(s[l] == s[r]) {
                    if(k == 0 || k == 1) {
                        dp[l][r] = 1;
                    }
                    else {
                        if(dp[l + 1][r - 1]) {
                            dp[l][r] = 1;
                        }
                    }
                }
                else {
                    dp[l][r] = 0;
                }
            }
        }
        for(int i = 1 ; i <= len ; i++) {
            ans[i] = ans[i - 1] + 1;
            for(int j = i - 1 ; j >= 1 ; j--) {
                if(dp[j][i]) {
                    ans[i] = min(ans[i] , ans[j - 1] + 1);
                }
            }
        }
        printf("Case %d: %d\n" , cnt , ans[len]);
    }
    return 0;
}
posted @ 2017-03-30 13:44  Gealo  阅读(248)  评论(0编辑  收藏  举报