问题
https://vjudge.net/problem/UVA-10453
分析
这道题应该是属于区间dp
dp[i][j].len表示[i,j]区间的生成回文字符串的最小代价,dp[i][j].s是生成的回文字符串。
如果s[i]==s[j],dp[i][j].len=dp[i+1][j-1].len+0, dp[i][j].s=s[i]+dp[i+1][j-1].s+s[j]
如果s[i]]!=s[j],dp[i][j].len=dp[i+1][j].len+1, dp[i][j].s=s[i]+dp[i+1][j].s+s[i]
或者 dp[i][j].len=dp[i][j-1].len+1, dp[i][j].s=s[j]+dp[i][j-1].s+s[j]
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <iterator>
using namespace std;
typedef long long LL;
const int maxn=1000+5;
int n,kase=0,dp[maxn][maxn],pre[maxn][maxn];
char s[maxn];
string ans;
void dfs(int i,int j){
if(j-i<=1){
if(j-i==1)
ans.push_back(s[i]);
return;
}
int temp=pre[i][j];
if(temp==1){
ans.push_back(s[i]);
dfs(i+1,j-1);
// ans.push_back(s[i]);
}else if(temp==2){
ans.push_back(s[i]);
dfs(i+1,j);
// ans.push_back(s[i]);
}else if(temp==3){
ans.push_back(s[j-1]);
dfs(i,j-1);
// ans.push_back(s[j]);
}
}
int main(void){
while(scanf("%s",s)!=EOF){
int len=strlen(s);
// for(int i=0;i<len;++i) dp[i][i+1]=0;
for(int i=len-1;i>=0;--i){
for(int j=i+2;j<=len;++j){
dp[i][j]=pre[i][j]=0;
if(s[i]==s[j-1]){
dp[i][j]=dp[i+1][j-1];
pre[i][j]=1;
}else if(dp[i+1][j]<=dp[i][j-1]){
dp[i][j]=dp[i+1][j]+1;
pre[i][j]=2;
}else {
dp[i][j] = dp[i][j - 1] + 1;
pre[i][j]=3;
}
}
}
printf("%d ",dp[0][len]);
ans.clear();
dfs(0,len);
// printf("%s",ans.c_str());
// if((dp[0][len]+len)%2==0){
// reverse(ans.begin(),ans.end());
// }else{
// ans.pop_back();
// reverse(ans.begin(),ans.end());
// }
// printf("%s\n",ans.c_str());
if((dp[0][len]+len)%2==0){
reverse_copy(ans.begin(),ans.end(),back_inserter(ans));
}else{
printf("%s\n",ans.c_str());
reverse_copy(ans.begin(),ans.end()-1,back_inserter(ans));
printf("%s\n",ans.c_str());
}
printf("%s\n",ans.c_str());
// break;
}
return 0;
}
//pqrsabcdpqrs