牛牛的回文串
牛牛的回文串
https://ac.nowcoder.com/acm/problem/21337
#include<bits/stdc++.h> using namespace std; #define ll long long /* 解决一个回文串可以发现,添加一个字符和删除一个字符是等价的,删除一个字符相当于在另一侧添加一个字符,所以只需要计算删除一个字符 所需要的的代价即可,删除一个字符可以用过 1. 先将该字符change成另一个字符再删除 2. 添加任意一个字符再修改成该字符相当于添加 3. 将该字符替换成另一个字符c在通过添加另一个字符 4. 将该字符替换成另一个字符c,再任意添加一个字符c1,再将c1替换成c 可以先用floyd来求出任意两个字符转换的最小代价,再去考虑上述四种情况求出cost 然后使用dp来解决问题 dp状态转移方程如下 dp[i][j]表示i~j是回文串的最小代价 从后往前和从前往后其实都一样 然后考虑dp[i+1~n]dp[j-1~n]都是已经处理好的了, 所以 if(s[i]==s[j])dp[i][j]=dp[i+1][j-1]; 考虑不相等的情况 1. 可以将s[i]删除val = dp[i+1][j] + cost[s[i]-'a'] 2. 可以将s[j]删除val = dp[i][j-1] + cost[s[j]-'a'] 3. 可以将s[i],s[j] 替换成某个字符 k 4. 可以将s[i]替换成s[j],或者s[j]替换成s[i] */ const int N = 60; ll dp[N][N]; ll cost[30],change[30][30]; ll cost_erase[30],cost_add[30]; const ll INF = 1e15+10; char s[N]; void floyd(){ for(int k=0;k<26;k++){ for(int i=0;i<26;i++){ for(int j=0;j<26;j++){ change[i][j]=min(change[i][j],change[i][k]+change[k][j]); } } } for(int i=0;i<26;i++){ for(int j=0;j<26;j++){ cost[i]=min(cost[i],min(cost_add[i],cost_erase[i])); cost[i]=min(cost[i],change[i][j]+min(cost_add[j],cost_erase[j])); cost[i]=min(cost[i],cost_add[j]+change[j][i]); for(int k=0;k<26;k++){ cost[i]=min(change[i][j]+cost_add[k]+change[k][j],cost[i]); } } } } int main(){ scanf("%s",s+1); int m; scanf("%d",&m); for(int i=0;i<26;i++){ cost_erase[i]=cost_add[i]=cost[i]=INF; for(int j=0;j<26;j++){ change[i][j]=INF; } } while(m--){ char op[20],ch[2],ch1[2]; int val; scanf("%s",op); if(op[0]=='e'){scanf("%s%d",ch,&val);cost_erase[ch[0]-'a']=min(cost_erase[ch[0]-'a'],1ll*val);} if(op[0]=='a'){scanf("%s%d",ch,&val);cost_add[ch[0]-'a']=min(cost_add[ch[0]-'a'],1ll*val);} if(op[0]=='c'){scanf("%s%s%d",ch,ch1,&val);change[ch[0]-'a'][ch1[0]-'a']=min(change[ch[0]-'a'][ch1[0]-'a'],1ll*val);} } floyd(); int len = strlen(s+1); for(int i=len;i>=1;i--){ for(int j=i+1;j<=len;j++){ dp[i][j]=INF; if(s[i]==s[j])dp[i][j]=dp[i+1][j-1]; dp[i][j]=min(dp[i][j],dp[i][j-1]+cost[s[j]-'a']); dp[i][j]=min(dp[i][j],dp[i+1][j]+cost[s[i]-'a']); dp[i][j]=min(dp[i][j],dp[i+1][j-1]+min(change[s[i]-'a'][s[j]-'a'],change[s[j]-'a'][s[i]-'a'])); for(int k=0;k<26;k++){ dp[i][j]=min(dp[i][j],dp[i+1][j-1]+change[s[i]-'a'][k]+change[s[j]-'a'][k]); } } } if(dp[1][len]==INF)printf("-1\n"); else printf("%lld\n",dp[1][len]); }