[POJ 1159]Palindrome[DP]

题目链接: [POJ 1159]Palindrome[DP]

题意分析:

给字符串添加最少的字符让其成为回文串。

解题思路:

dp[i][j]代表,区间[i,j]变成回文要插入的最少字符数。如果s[i] == s[j],那么dp[i][j] = dp[i + 1][j - 1];否则,dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1(由已经构成回文的区间添加一个字符)。本题int,5000*5000大概90000k,所以使用short降低一半,而且short最大值为3e4左右,比最大可能插入值要大,所以可行

个人感受:

状态想好了,就是不知道怎么写循环= =,最后不得不用上记忆化搜索。。。。。然后边界条件没处理好,让我太迷了。。。。。

具体代码如下:

#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define si short
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;

const int MAXN = 5e3 + 100;

si mmin(si a, si b) {
    return a < b ? a : b;
}

si dp[MAXN][MAXN];
char s[MAXN];

si dfs(si l, si r) {
    si &ret = dp[l][r];
    if (ret >= 0) return ret;
    if (l + 1 == r) return ret = (s[l] != s[r]);
    if (l == r) return ret = 0;

    if (s[l] == s[r]) ret = dfs(l + 1, r - 1);
    else ret = mmin(dfs(l + 1, r), dfs(l, r - 1)) + 1;

    return ret;
}

int main()
{
    int n;
    while (~scanf("%d%s", &n, s)){
        memset(dp, -1, sizeof dp);
        printf("%d\n", dfs(0, n - 1));
    }
    return 0;
}

16/03/14 update:补上循环写法:比记忆化快好多。。。。

#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define si short
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;

const int MAXN = 5e3 + 100;

si mmin(si a, si b) {
    return a < b ? a : b;
}

si dp[MAXN][MAXN];
char s[MAXN];

int main()
{
    int n;
    while (~scanf("%d%s", &n, s)){
        for (int i = n - 1; i >= 0; --i) {
            dp[i][i] = 0;
            for (int j = i + 1; j < n; ++j) {
                if (s[i] == s[j] && i + 1 < j) dp[i][j] = dp[i + 1][j - 1];
                else if (s[i] == s[j]) dp[i][j] = 0;
                else dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
            }
        }
        printf("%d\n", dp[0][n - 1]);
    }
    return 0;
}


你可能感兴趣的:(dp)