题意
给出一个字符串,问最小所需的字符数量使得插入这些字符后,该字符串成为回文串
回文串+区间dp,dp[i][j]表示使给定字符串的i-j段成为回文串的最小插入字符数量,
在记忆化搜索中有三类情况,一种是i>=j,i>j的段是无意义的,而i=j的段本身肯定是回文,不需插入字符,都是0,之后分c[i]=c[j]和c[i]!=c[j]两类情况,如果c[i]=c[j],继续往这段字符串的中间搜索,即dfs(i+1,j-1),否则我们尝试在最左端和最右端插入字符并取最小值,即min(dfs(i+1,j)+1,dfs(i,j-1)+1)
#include<bits/stdc++.h>
using namespace std;
const int MAXN=110;
char c[MAXN];
int dp[MAXN][MAXN];
bool is_palindrome(int i,int j){
for(int pos=i;pos<=(i+j)/2;pos++){
if(c[pos]!=c[j-(pos-i)]) return false;
}
return true;
}
void init(){
memset(dp,-1,sizeof(dp));
}
int dfs(int i,int j){
int ans=0;
if(dp[i][j]!=-1) return dp[i][j];//已存在就不用再搜素
if(i>=j) return dp[i][j]=0;
else if(c[i]==c[j]){
return dp[i][j]=dfs(i+1,j-1);//搜素下一区间
}
else{
return dp[i][j]=min(dfs(i+1,j)+1,dfs(i,j-1)+1);//尝试在左右加字符
}
}
int main(){
int T,cnt=0;
scanf("%d",&T);
while(T--){
init();
scanf("%s",c);
int len=strlen(c)-1;
if(is_palindrome(0,len)==1){
printf("Case %d: 0\n",++cnt);
continue;
}
dfs(0,len);
printf("Case %d: %d\n",++cnt,dp[0][len]);
}
}