zoukankan      html  css  js  c++  java
  • [FZU2254]英语考试

    在过三个礼拜,YellowStar有一场专业英语考试,因此它必须着手开始复习。

    这天,YellowStar准备了n个需要背的单词,每个单词的长度均为m。

    YellowStar准备采用联想记忆法来背诵这n个单词:

    1、如果YellowStar凭空背下一个新词T,需要消耗单词长度m的精力

    2、如果YellowSatr之前已经背诵了一些单词,它可以选择其中一个单词Si,然后通过联想记忆的方法去背诵新词T,需要消耗的精力为hamming(Si, T) * w。

    hamming(Si, T)指的是字符串Si与T的汉明距离,它表示两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。

    由于YellowStar还有大量繁重的行政工作,因此它想消耗最少的精力背诵下这n个单词,请问它最少需要消耗多少精力。

    Input

    包含多组测试数据。

    第一行为n, m, w。

    接下来n个字符串,每个字符串长度为m,每个单词均为小写字母'a'-'z'组成。

    1≤n≤1000

    1≤m, w≤10

    Output

    输出一个值表示答案。

    Sample Input

    3 4 2
    abch
    abcd
    efgh

    Sample Output

    10

    Hint

    最优方案是:先凭空记下abcd和efgh消耗精力8,在通过abcd联想记忆去背诵abch,汉明距离为1,消耗为1 * w = 2,总消耗为10。

    最小生成树。

    我们先处理联想记忆法,我们把a向b连一条权值为联想记忆法代价的双向边。

    然后处理直接记忆,我们新开一个节点,把它向每个节点连一条权值为m的边。

    然后跑Prim即可。

    双向边要开2倍空间。Prim要加一个数组表示当前节点在不在最小生成树内(比dij多开一个数组)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int h[1010],to[2101000],nxt[2101000],cost[2101000],k=0;
    char c[1010][11];int d[1010];bool used[1010];
    typedef pair<int,int> P;
    priority_queue<P,vector<P>,greater<P> >q;
    void ins(int u,int v,int c){nxt[++k]=h[u];h[u]=k;to[k]=v;cost[k]=c;}
    int prim(int S)
    {
        memset(d,63,sizeof(d));memset(used,0,sizeof(used));
        d[S]=0;q.push(P(d[S],S));int ans=0;
        while(!q.empty())
        {
            P p=q.top();q.pop();int u=p.second;
            if(used[u])continue;used[u]=1;
            ans+=d[u];
            for(int i=h[u];i;i=nxt[i])
            {
                int v=to[i];
                if(cost[i]<d[v]){d[v]=cost[i];q.push(P(d[v],v));}
            }
        }
        return ans;
    }
    int main()
    {
        int n,m,w;
        while(scanf("%d%d%d",&n,&m,&w)!=EOF)
        {
            memset(h,0,sizeof(h));k=0;
            char s[11];
            for(int i=1;i<=n;i++){scanf("%s",s);for(int j=0;j<m;j++)c[i][j]=s[j];}
            for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                if(i==j)continue;
                int sum=0;
                for(int k=0;k<m;k++)if(c[i][k]!=c[j][k])sum++;
                ins(i,j,sum*w);ins(j,i,sum*w); 
            }
            for(int i=1;i<=n;i++)ins(n+1,i,m),ins(i,n+1,m);
            printf("%d
    ",prim(n+1));
        }
            
    }
  • 相关阅读:
    oracle 内连接、外连接、自然连接、交叉连接练习
    oracle语句练习
    简单的oracle sql语句练习
    CountDownLatch 使用方法
    T1,T2,T3 三个线程顺序执行
    【2018 校招真题】斐波那契数列
    使用自己的域名解析 cnblogs 博客
    在 github 中新建仓库后,如何上传文件到这个仓库里面。
    数据库常用语句整理
    使用 JQuery 实现将 table 按照列排序
  • 原文地址:https://www.cnblogs.com/lher/p/7857169.html
Copyright © 2011-2022 走看看