UVa 10739 - String to Palindrome

传送门

UVa 10739 - String to Palindrome

题意

给一个字符串,可以再任意位置增加、删去、替换字符,求让他变成回文串的最少操作数

思路

参考。用dp[i][j]表示区间i~j的最少步数、

  1. s[i] == s[j] 显然只需要考虑i与j之间的字符串即可,此时dp[i][j] = dp[i+1][j-1]。

  2. s[i] != s[j]. 这时就要考虑到底是删除,插入还是替换。由于删除和插入所需要的操作步数以及影响是一致的,只需要考虑插入或者删除就行了。对于插入则dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1;对于替换则有dp[i][j] = min(dp[i][j], dp[i+1][j-1] + 1)

想了很久想不懂,只能先背下来了。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1100;

char str[MAXN];
int dp[MAXN][MAXN];

int DFS(int x, int y)
{
    int &ans = dp[x][y];
    if (ans != -1)
        return ans;
    if (x > y)
        return ans = 0;
    if (str[x] == str[y])
        ans = DFS(x + 1, y - 1);
    else
        ans = min(min(DFS(x, y - 1), DFS(x + 1, y)), DFS(x + 1, y - 1)) + 1;
    return ans;
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int T, i, j, cases = 0;
    scanf("%d%*c", &T);
    while (T--)
    {
        memset(dp, -1, sizeof dp);
        gets(str);
        int len = strlen(str);
        DFS(0, len - 1);
        printf("Case %d: %d\n", ++cases, dp[0][len - 1]);
    }
    return 0;
}

Powered by Jekyll and Theme by solid