啊...比赛的时候输入打错了,结束之后还照着题解把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 ;
}

最新文章

  1. LINQ系列:LINQ to SQL Group by/Having分组
  2. 网站添加数据出错,原来是MS SQL Server2008日志文件占据空间过大导致的
  3. Ubuntu 下apache2开启rewrite隐藏index.php
  4. Scala 深入浅出实战经典 第78讲:Type与Class实战详解
  5. 无法创建链接服务器 &quot;(null)&quot; 的 OLE DB 访问接口 &quot;Microsoft.Ace.OLEDB.12.0&quot; 的实例。
  6. EhCache 分布式缓存/缓存集群
  7. lintcode:落单的数
  8. Android开发UI之补间动画-Tween Animation
  9. VS2010 Cstring to int
  10. Python collections.defaultdict 笔记
  11. [置顶] JAVA概述(6)常量,关键字,进制转换
  12. 从键盘或文件中获取标准输入:read命令
  13. Centos6.9minimal安装图形化界面
  14. AI2(App Inventor 2)离线版服务器网络版
  15. 2019.03.26 bzoj4448: [Scoi2015]情报传递(归并排序+树链剖分)
  16. ArcGIS案例学习笔记-栅格数据分区统计(平均高程,污染浓度,污染总量,降水量)
  17. Qt经典—线程、事件与Qobject
  18. Mysql InnoDB的四个事务隔离级别和(分别逐级解决的问题)脏读,不可重复读,虚读
  19. 【python】Django设置SESSION超时时间没有生效?
  20. Android——加载模式

热门文章

  1. 中文情感分析 glove+LSTM
  2. mysql根据用户的邀请码查询该用户所有的上级
  3. 设置NODE_ENV=test环境变量
  4. 工作用linux命令汇总
  5. Java基础学习总结(82)——Java泛型实例教程
  6. Intellij IDEA神器居然还有这些小技巧---超级好用的
  7. noip模拟赛 梦想
  8. Oracle创建表空间、用户名、密码步骤教程
  9. 模拟赛 Problem 1 高级打字机(type.cpp/c/pas)
  10. MyBatis3-传递多个参数(Multiple Parameters)