zoukankan      html  css  js  c++  java
  • Codeforces Beta Round #33 (Codeforces format) B. String Problem(floyd最短路)

    地址: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;
            }
    }
  • 相关阅读:
    Leetcode 15 3Sum
    Leetcode 383 Ransom Note
    用i个点组成高度为不超过j的二叉树的数量。
    配对问题 小于10 1.3.5
    字符矩阵的旋转 镜面对称 1.2.2
    字符串统计 连续的某个字符的数量 1.1.4
    USACO twofive 没理解
    1002 All Roads Lead to Rome
    USACO 5.5.1 求矩形并的周长
    USACO 5.5.2 字符串的最小表示法
  • 原文地址:https://www.cnblogs.com/liyexin/p/12708784.html
Copyright © 2011-2022 走看看