啊...比赛的时候输入打错了,结束之后还照着题解把DP部分重构了一遍然而还是WA...样例都没过,然后直接输了-1

明显的DP...而且数据范围这么小,显然怎么搞都可以...

而且这样的回文的DP是很经典的DP啊

f[i][j]表示从i到j所需要最少的价格

$$f[i][j]=\begin{cases}f[i+1][j-1]&& \text{s[i]=s[j]}\\min\{f[i+1][j]+cst[s[i]],f[i][j-1]+cst[a[j]],f[i+1][j-1]+dis[a[i]][a[j]]\}&& \text{}\end{cases}$$

其中cst[i],dis[i][j]分别表示把i消掉(变成回文)和把i变成j所要的最小代价

有点恶心的是...add erase change可以组合起来形成新的操作

比如说change a->b等价于erase a再add b,显然我们要进行分类讨论

不难发现有这些情况:

$$\begin{cases}把a删掉再加上b& \text{}\\加上a再换成b&& \text{}\\把a变成b再删掉 &&\text{}\\在a后面再加一个a &&\text{}\\直接删掉a &&\text{}\end{cases}$$

而且这些操作互相之间是有联系的...所以操作顺序要改一下

然后因为可能会有a->b->c->d之类的路径存在,我们可以跑Floyd来求得最终的dis[i][j]

然后就可以愉快的DP了,注意填表顺序(有点像区间DP)...

#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
inline int read(){
int ans=,f=;char chr=getchar();
while(!isdigit(chr)){if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)){ans=(ans<<)+(ans<<)+chr-;chr=getchar();}
return ans*f;
}int n,m,dis[][],era[],add[],f[][],cst[];
char s[],opt[],kk[],ccc[];
signed main(){//比赛的时候读入读错了...自闭
scanf("%s",s+);
for(register int i=;i<=;i++) cst[i]=add[i]=era[i]=1e14;
for(register int i=;i<=;i++) for(int j=;j<=;j++)dis[i][j]=1e14;
n=strlen(s+);m=read();
for(register int i=,x;i<=m;++i){
scanf("%s%s",opt,kk);
if(opt[]=='c'){
scanf("%s",ccc);
x=read();
dis[kk[]][ccc[]]=min(x,dis[kk[]][ccc[]]);
}else if(opt[]=='e'){
x=read();
era[kk[]]=min(era[kk[]],x);
}else{
x=read();
add[kk[]]=min(add[kk[]],x);
}
}
for(register int i='a';i<='z';i++) dis[i][i]=;
for(register int k='a';k<='z';k++)
for(register int i='a';i<='z';i++)
for(register int j='a';j<='z';j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for(register int i='a';i<='z';i++)
for(register int j='a';j<='z';++j){
cst[i]=min(cst[i],min(add[i],era[i])),
cst[i]=min(cst[i],dis[i][j]+min(era[j],add[j])),
cst[i]=min(cst[i],add[j]+dis[j][i]);
for(register int k='a';k<='z';++k)
cst[i]=min(cst[i],dis[i][j]+add[k]+dis[k][j]);
}
for(register int i=n;i>=;i--){
for(register int j=i+;j<=n;++j){f[i][j]=1e14;
if(s[i]==s[j]) f[i][j]=f[i+][j-];
f[i][j]=min(f[i][j],f[i+][j]+cst[s[i]]);
f[i][j]=min(f[i][j],f[i][j-]+cst[s[j]]);
f[i][j]=min(f[i][j],f[i+][j-]+min(dis[s[j]][s[i]],dis[s[i]][s[j]]));
for(int k='a';k<='z';++k)
f[i][j]=min(f[i][j],f[i+][j-]+dis[s[i]][k]+dis[s[j]][k]);
}
}
if(f[][n]==1e14) cout<<-;else cout<<f[][n];
return ;
}

longpo的回文的更多相关文章

  1. bzoj 1236: longpo的回文

    1236: longpo的回文 题目描述 一个字符串如果从左到右和从右到左读的结果是一样的,我们称之为回文串.现在给定一个字符串,我们有三种操作: 1.     添加一个字母在任何位置(可以在首尾添加 ...

  2. LeetCode[5] 最长的回文子串

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  3. 最长回文子串-LeetCode 5 Longest Palindromic Substring

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  4. [LeetCode] Longest Palindrome 最长回文串

    Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...

  5. [LeetCode] Palindrome Pairs 回文对

    Given a list of unique words. Find all pairs of distinct indices (i, j) in the given list, so that t ...

  6. [LeetCode] Palindrome Permutation II 回文全排列之二

    Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...

  7. [LeetCode] Palindrome Permutation 回文全排列

    Given a string, determine if a permutation of the string could form a palindrome. For example," ...

  8. [LeetCode] Palindrome Linked List 回文链表

    Given a singly linked list, determine if it is a palindrome. Follow up: Could you do it in O(n) time ...

  9. [LeetCode] Shortest Palindrome 最短回文串

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

随机推荐

  1. Shock wave

    ** shock wave thickness of shock wave is order of 1e-7 m why governed by Euler Equation? P334 shock ...

  2. BZOJ 4006 Luogu P3264 [JLOI2015]管道连接 (斯坦纳树、状压DP)

    题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4006 (luogu)https://www.luogu.org/probl ...

  3. UVA 12697 Minimal Subarray Length

    Minimal Subarray Length Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVA ...

  4. POJ 3101 大数+gcd

    题目大意: 星星作圆周运动的周期给出,若已连成一条线,下一次所有星星在同一条线上的时间 用分数形式输出 这里我们可以利用追及问题来计算出两个星星之间连成一条直线的时间,也即速度快的星星追上速度慢的星星 ...

  5. [luoguP1103] 书本整理(DP)

    传送门 以 去掉多少个 为阶段不好做. 去掉 k 个也可以变成选 n - k 个 f[i][j] 表示前 i 个数中 选 j 个的最优解,a[i] 必选 f[i][j] = min(f[i][j], ...

  6. KMP超强模板贴一份

    )== ) {         );         next[]=; ;         ;i<=n;i++) {             ]!=str[i]) j=next[j];      ...

  7. 分块试水--CODEVS5037 线段树练习4加强版

    感觉这才算入门题吧..前面那些线段树练习,改几个字符就过了一定要搞成几道题.. n<=2e5的数列,给常数K<=2e5,m<=2e5个操作,区间加,问一个区间里K的倍数. 这题空间? ...

  8. ORA-12541:TNS:无监听程序

    安装oracle以后,sql plus可以正常登陆,pl/sql登陆时报错ORA-12541:TNS:无监听程序,解决方案如下: http://blog.csdn.net/hao134838/arti ...

  9. codevs——1530 大质数

    1530 大质数  时间限制: 1 s  空间限制: 1000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 小明因为没做作业而被数学老师罚站,之后数学老师 ...

  10. CString、char*与string的区别

    三者的区别 CString 是MFC或者ATL中的实现: string 是C++标准库中的实现: char* 为C编程中最常用的字符串指针,一般以’\0’为结束标志. string和CString均是 ...