XJOI 3867 LLL的迴文串
阿新 • • 發佈:2018-11-01
題意
LLL喜歡迴文串,CCCLLL給了LLL一個字串 \(S\) ,LLL想把 \(S\) 變成迴文串
LLL可以做如下三種操作
- 在任意位置增加一個字元
- 刪除一個字元
- 改變一個字元
每種操作都有限定的字元,比如,只能刪除'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 c1 c2\) 都是小寫字母
\(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\) 變換為 \(j\) 不一定要直接轉換,可能會有中介字元,所以我們用類似floyd的三重迴圈求出 \(c[i][j]\)。
然後求 \(mt[i]\) ,我們發現,把字元 \(i\) 消去有五種方法:
- 增加一個和 \(i\) 一樣的字元
- 直接刪除 \(i\)
- 增加一個字元 \(j\) ,再把 \(j\) 變為 \(i\)
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;
}