$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

XJOI 3867 LLL的回文串

题意

LLL喜欢回文串,CCCLLL给了LLL一个字符串 \(S\) ,LLL想把 \(S\) 变成回文串
LLL可以做如下三种操作

  1. 在任意位置增加一个字符
  2. 删除一个字符
  3. 改变一个字符

每种操作都有限定的字符,比如,只能删除'a',增加'b',把'c'变成'd'等等
每种操作都有相应的代价
\(m\) 条语句来描述能进行的操作
add c x 表示增加 \(c\) 字符需要 \(x\) 的代价
erase c x表示删除 \(c\) 字符需要 \(x\) 的代价
change c1 c2 x表示将 \(c_1\) 改成 \(c_2\) 需要 \(x\) 的代价
求LLL想要得到回文串需要的最少代价
如果不行输出 \(-1\)

输入格式

第一行输入一个字符串 \(S\) (都是小写字母)表示CCCLLL给LLL的串 \((1≤|S|≤50)\)
第二行输入一个整数\(m (0≤m≤50)\)
接下来 \(m\) 行的格式是

add c x
erase c x
change c1 c2 x

三种中的一种
\(c,c_1,c_2\) 都是小写字母
\(1≤x≤100000\)
所有允许的操作去除 \(x\) 部分后都是不同的

输出格式

输出一个整数

样例输入&输出

样例1

racecar
0

0

样例2

topcoder
7
erase t 1
erase o 1
erase p 1
erase c 1
erase d 1
erase e 1
erase r 1

5

样例3

topcoder
7
erase t 10
erase o 1
erase p 1
erase c 1
erase d 1
erase e 1
erase r 1

7

样例4

caaaaaab
6
change b a 100000
change c a 100000
change c d 50000
change b e 50000
erase d 50000
erase e 49999

199999

样例5

moon
6
erase o 5
add u 7
change d p 3
change m s 12
change n d 6
change s l 1

-1

分析

我们设 \(mt[i]\) 表示把字符 \(i\) 消去的最小代价, \(c[i][j]\) 表示把 \(i\) 变成 \(j\) 所需的最小代价。
由于 \(i\) 变换为 \(j\) 不一定要直接转换,可能会有中介字符,所以我们用类似floyd的三重循环求出 \(c[i][j]\)
然后求 \(mt[i]\) ,我们发现,把字符 \(i\) 消去有五种方法:

  1. 增加一个和 \(i\) 一样的字符
  2. 直接删除 \(i\)
  3. 增加一个字符 \(j\) ,再把 \(j\) 变为 \(i\)
  4. \(i\) 变成 \(j\) ,再删除
  5. \(i\) 变成 \(j\) ,再插入一个 \(j\) 字符

然后就区间dp就好了。转移方程:
\(i,j,k\in [1,n]\)
\(dp[i][j]=\min(dp[i][j],dp[i+1][j]+mt[a[i]],dp[i][j-1]+mt[a[j]],dp[i+1][j-1]+c[a[i]][a[j]],dp[i+1][j-1]+c[a[j]][a[i]],dp[i+1][j-1]+c[a[i]][k]+c[a[j]][k])\)
\(if(a[i+1]==a[j-1])\;dp[i][j]=\min(dp[i][j],dp[i+1][j-1])\)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 55
#define INF 200000000
using namespace std;
char s[maxn],tmp[2],tmp1[2];
int a[maxn],n,er[26],ad[26],mt[26],c[26][26],dp[maxn][maxn];
void init(){
	scanf("%s",s);
	n=strlen(s);
	for(int i=1;i<=n;i++){
		a[i]=s[i-1]-'a';
	}
	for(int i=0;i<26;i++){
		er[i]=ad[i]=mt[i]=INF;
		for(int j=0;j<26;j++)c[i][j]=INF;
	}
	int m,x;
	scanf("%d",&m);
	while(m--){
		scanf("%s",s);
		if(*s=='e'){
			scanf("%s%d",tmp,&x);
			er[*tmp-'a']=min(er[*tmp-'a'],x);
		}
		else if(*s=='a'){
			scanf("%s%d",tmp,&x);
			ad[*tmp-'a']=min(ad[*tmp-'a'],x);
		}
		else{
			scanf("%s%s%d",tmp,tmp1,&x);
			c[*tmp-'a'][*tmp1-'a']=min(c[*tmp-'a'][*tmp1-'a'],x);
		}
	}
}
void floyd(){
	for(int k=0;k<26;k++){
		for(int i=0;i<26;i++){
			for(int j=0;j<26;j++){
				c[i][j]=min(c[i][j],c[i][k]+c[k][j]);
			}
		}
	}
	for(int i=0;i<26;i++){
		for(int j=0;j<26;j++){
			mt[i]=min(mt[i],min(min(er[i],ad[i]),min(ad[j]+c[j][i],min(c[i][j]+er[j],c[i][j]+ad[j]))));
			for(int k=0;k<26;k++){
				mt[i]=min(mt[i],c[i][j]+ad[k]+c[k][j]);
			}
		}
	}
}
int main(){
	init();
	floyd();
	for(int len=2;len<=n;len++){
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			dp[i][j]=INF;
			if(a[i]==a[j])dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
			dp[i][j]=min(dp[i][j],min(min(dp[i+1][j]+mt[a[i]],dp[i][j-1]+mt[a[j]]),
			min(dp[i+1][j-1]+c[a[i]][a[j]],dp[i+1][j-1]+c[a[j]][a[i]])));
			for(int k=0;k<26;k++){
				dp[i][j]=min(dp[i][j],dp[i+1][j-1]+c[a[i]][k]+c[a[j]][k]);
			}
		}
	}
	printf("%d\n",dp[1][n]==INF?-1:dp[1][n]);
	return 0;
}
posted @ 2018-11-01 08:20  chc_1234567890  阅读(195)  评论(0编辑  收藏  举报