地址:http://codeforces.com/contest/33/problem/B
很老的题了,今天被学长拉出来,就做做看。
题意:给出两个字符串,给出n个 a b x,表明字符a可以变成b,每次花费为x。问要想把这俩字符串变成一样的,最少花费多少。无法变就输出-1。
解析:刚开始以为,每次只看同一个位置,能互换就行,洋洋洒洒写了100多行,一直WA7。原来,一个字符,不一定要变成另一个字符串对应位置的那个字符,可以变成其它的,只要保证花费最小就行。所以我们把26个字母之间互换的花费存起来,跑一遍floyd,就得出了两两变化的最小花费,然后每次看一个位置,就遍历26个字符,看同一位置的这俩字符变成同一个字符所需的花费,求最小就可以了。如果最小值得不到更新,就说明这两个字符串没办法变成同样的,输出-1。
#include<iostream> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int maxn=1e5+10; const int inf = 0x3f3f3f3f; int mp[28][28]; char mid[maxn]; char s1[maxn],s2[maxn]; int d[28][28]; void init() { for(int i= 0;i<26;i++) for(int j=0;j<26;j++) { if(i==j) mp[i][j]=0; else mp[i][j]=inf; } } void floyd() { for(int i=0;i<26;i++) for(int j=0;j<26;j++) d[i][j]=mp[i][j]; for(int k=0;k<26;k++) for(int i=0;i<26;i++) for(int j=0;j<26;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } int main() { cin>>s1; cin>>s2; int len1=strlen(s1),len2=strlen(s2); int n; cin>>n; init(); char ch1; while(n--) { scanf(" %c",&ch1); char ch2; int x; scanf(" %c %d",&ch2,&x); int a=ch1-'a'; int b=ch2-'a'; mp[a][b]=min(mp[a][b],x); } if(len1!=len2) { cout<<"-1"<<endl; return 0; } floyd(); int ok=0; int tot=0; int sum=0; for(int i=0;i<len1;i++) { if(s1[i]==s2[i]) { mid[tot++]=s1[i]; continue; } int minn=inf; int a=s1[i]-'a'; int b=s2[i]-'a'; for(int j=0;j<26;j++) { int x1=d[a][j]; int x2=d[b][j]; if(x1!=inf&&x2!=inf&&minn>(x1+x2)) { minn=x1+x2; mid[tot]=char('a'+j); } } if(minn==inf) { ok=1;break; } // cout<<minn<<endl; tot++; sum+=minn; } if(ok) cout<<"-1"<<endl; else { cout<<sum<<endl; cout<<mid<<endl; } }