题目大意:给一个字符串,可以对该字符串进行增,删,替换三种操作,求用最少的操作让字符串变成回文串
解题思路:又是字符串的回文问题,想了很久,思来想去怎么替换,怎么删除,怎么增加,结果想偏了,他只是问最少操作数,而不是要你修改。。。添加和删除这两个操作相对说是等价的,这样只需要考虑添加和替换两个操作了,这样问题就转换了,设dp[i][j]表示第i个字符串到第j个字符串变成回文字符串的最少操作,则
1.如果str[i] == str[j],则dp[i][j] = dp[i+1][j-1]
2.如果str[i] != str[j],则dp[i][j] = min(dp[i+1][j],dp[i][j-1],dp[i+1][j-1]) + 1,dp[i+1][j-1]是替换的,其余两个是添加的,dp[i+1][j]是在j后面添加str[i],dp[i][j-1]是在i的前面添加str[j]
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 1005
#define INF 0x3f3f3f3f
char str[maxn];
int dp[maxn][maxn];
int DP(int i, int j) {
if(dp[i][j] != -1)
return dp[i][j];
if(i == j || i == j + 1)
return dp[i][j] = 0;
if(str[i] == str[j])
dp[i][j] = DP(i+1,j-1);
else {
dp[i][j] = DP(i+1,j);
if(DP(i+1,j-1) < dp[i][j])
dp[i][j] = DP(i+1,j-1);
if(DP(i,j-1) < dp[i][j])
dp[i][j] = DP(i,j-1);
dp[i][j] += 1;
}
return dp[i][j];
}
int main() {
int test;
scanf("%d\n",&test);
int mark = 1;
while(test--) {
gets(str);
int len = strlen(str);
memset(dp,-1,sizeof(dp));
printf("Case %d: %d\n",mark++,DP(0,len-1));
}
return 0;
}