列表

详情


NC21337. 牛牛的回文串

描述

牛牛喜欢回文串,牛妹给了牛牛一个字符串S,牛牛想把S变成回文串
牛牛可以做如下三种操作
1:在任意位置增加一个字符
2:删除一个字符
3:改变一个字符

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

输入描述

第一行输入一个字符串S(都是小写字母)表示牛妹给牛牛的串(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

输入:

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

示例3

输入:

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

示例4

输入:

xab
7
change a c 1
change b d 1
change c e 1
change d e 1
add y 1
change y z 1
change x z 1

输出:

7

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 4ms, 内存消耗: 612K, 提交时间: 2020-03-09 18:09:35

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll inf = 1e15;

ll a[30],e[30],c[30][30],dp[60][60],x;
string s,t;
char c1,c2;

void init(){
	for(int i=0;i<26;i++){
		a[i]=e[i]=inf;
		for(int j=0;j<26;j++){
			if(i==j){
				c[i][j]=0;
			}else{
				c[i][j]=inf;
			}
		}
	}
}

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++){
			c[i][j]=min(c[i][j],e[i]+a[j]);
			e[i]=min(e[i],c[i][j]+e[j]);
			a[j]=min(a[j],a[i]+c[i][j]);
		}
	} 
}

int main(){
	init();
	cin>>s;
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		cin>>t;
		if(t=="add"){
			cin>>c1>>x;
			a[c1-'a']=min(a[c1-'a'],x);
		}else if(t=="erase"){
			cin>>c1>>x;
			e[c1-'a']=min(e[c1-'a'],x);
		}else{
			cin>>c1>>c2>>x;
			c[c1-'a'][c2-'a']=min(c[c1-'a'][c2-'a'],x);
		} 
	}
	Floyd();
	for(int i=2;i<=s.size();i++){
		for(int j=0;j+i-1<s.size();j++){
			int l=j,r=j+i-1;
			dp[l][r]=inf;
			dp[l][r]=min(dp[l][r],min(dp[l+1][r]+e[s[l]-'a'],dp[l][r-1]+e[s[r]-'a']));
			dp[l][r]=min(dp[l][r],dp[l+1][r-1]+e[s[l]-'a']+e[s[r]-'a']);
			for(int k=0;k<26;k++){
				dp[l][r]=min(dp[l][r],dp[l+1][r-1]+c[s[l]-'a'][k]+c[s[r]-'a'][k]);
				dp[l][r]=min(dp[l][r],min(dp[l+1][r]+a[k]+c[s[l]-'a'][k],dp[l][r-1]+a[k]+c[s[r]-'a'][k]));
			}
		}
	}
	cout<<((dp[0][s.size()-1]==inf)?-1:dp[0][s.size()-1])<<endl;
	return 0;
} 

C++(clang++11) 解法, 执行用时: 15ms, 内存消耗: 888K, 提交时间: 2021-01-25 22:35:00

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define chkmin(x,y) x=min(x,y)
int del[300],add[300],c[300][300];
LL f[55][55];
char s[55];
int m,n;
int main()
{
	cin>>(s+1);
	n=strlen(s+1);
	cin>>m;
	memset(del,0x3f,sizeof(del));
	memset(add,0x3f,sizeof(del));
	memset(c,0x3f,sizeof(c));
	for(int i=1;i<=m;++i)
	{
		char opt[10];
		char c1,c2;
		int cost;
		cin>>(opt+1);
		if(opt[1]=='c')
		{
			cin>>c1>>c2>>cost;
			c[c1-'a'+1][c2-'a'+1]=cost;
		}
		else
		{
			cin>>c1>>cost;
			if(opt[1]=='a')
			add[c1-'a'+1]=cost;
			else 
			del[c1-'a'+1]=cost;
		}
	}
	for(int i=1;i<=26;++i)
	c[i][i]=0;
	for(int k=1;k<=26;++k)
	for(int i=1;i<=26;++i)
	for(int j=1;j<=26;++j)
	c[i][j]=min(c[i][j],c[i][k]+c[k][j]);
	for(int i=1;i<=26;++i)
	for(int j=1;j<=26;++j)
	{
		add[i]=min(add[i],add[j]+c[j][i]);
		del[i]=min(del[i],c[i][j]+del[j]);
	}
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=n;++i)
	f[i][i]=0,f[i][i-1]=0;
	for(int len=2;len<=n;++len)
	for(int l=1;l<=n-len+1;++l)
	{
		int r=l+len-1;
		int ll=s[l]-'a'+1,rr=s[r]-'a'+1;
		chkmin(f[l][r],f[l][r-1]+del[rr]);
		chkmin(f[l][r],f[l+1][r]+del[ll]);
		for(int k=1;k<=26;++k)
		{
			chkmin(f[l][r],f[l][r-1]+add[k]+c[rr][k]);
			chkmin(f[l][r],f[l+1][r]+add[k]+c[ll][k]);
			chkmin(f[l][r],f[l+1][r-1]+c[ll][k]+c[rr][k]);
		}
	}
	cout<<(f[1][n]>=0x3f3f3f3f?-1:f[1][n]);
	return 0;
}

上一题