英语考试 FZU - 2254 (最小生成树)

先选一个单词出来完全自己背,然后从这个单词到其他各个单词所需要的精力看成距离,然后用最小生成树把这些单词连接起来,就是通过我现在选的这个单词到其他各个单词的最小精力,然后再加上把这个单词背起来的精力,就是答案

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) (x & (-x))

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1105;
const int maxm = 400;
const int mod = 10007;
using namespace std;

int n, m, tol, T;
char str[maxn][20];
int maps[maxn][maxn];
int dis[maxn];
bool vis[maxn];

void init() {
    memset(str, 0, sizeof str);
    memset(vis, 0, sizeof vis);
    memset(dis, inf, sizeof dis);
    memset(maps, inf, sizeof maps);
}

int Prim() {
    int ans = 0;
    for(int i=1; i<=n; i++)    dis[i] = maps[1][i];
    dis[1] = 0;
    vis[1] = true;
    for(int k=2; k<=n; k++) {
        int p = 0;
        for(int i=1; i<=n; i++) {
            if(!vis[i] && dis[p] > dis[i]) {
                p = i;
            }
        }
        vis[p] = true;
        ans += dis[p];
        for(int i=1; i<=n; i++) {
             if(!vis[i] && dis[i] > maps[p][i]) {
                dis[i] = maps[p][i];
             }
        }
    }
    return ans;
}

int main() {
    int w;
    while(~scanf("%d%d%d", &n, &m, &w)) {
        init();
        for(int i=1; i<=n; i++)    scanf("%s", str[i]+1);
        for(int i=1; i<=n; i++) {
            for(int j=i+1; j<=n; j++) {
                int nn = 0;
                for(int k=1; k<=m; k++) {
                    if(str[i][k] != str[j][k])    nn++;
                }
                maps[i][j] = maps[j][i] = min(m, nn*w);
            }
        }
        //for(int i=1; i<=n; i++)    for(int j=1; j<=n; j++)    printf("%d%c", maps[i][j], j==n ? '\n' : ' ');
        int ans = Prim() + m;
        printf("%d\n", ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/H-Riven/p/9389095.html