poj1789(prim)

prim和kruskal都是求解最小生成树的算法。这道题题意就是有N个字符串就是N个节点,而字符串之间的距离就是节点边的长度,求其最小生成树的边权和。

由于是第一次用prim,所以在求安全边的时候采用的是暴力的方法,所以我这个算法是O(n^2)的,跑了近1500ms,吓出一身冷汗……如果采用优先队列或者堆等数据结构应该会快,但是代码也会相应复杂了。

#include <iostream>
#include <string>
using namespace std;

int n;
string str[2001];
int dis[2001][2001];
int key[2001];
bool visited[2001];

const int LEN = 7;

int calDis(string str1, string str2)
{
    int ans = 0;
    for (int i = 0; i < LEN; i++){
        if (str1[i] != str2[i]){
            ans++;
        }
    }
    return ans;
}

int prime()
{
    int sum = 0;
    visited[0] = true;
    for (int i = 0; i < n; i++){
        key[i] = dis[0][i];
    }
    for (int i = 1; i < n; i++){
        int min = 100;
        int index = 0;
        for (int j = 0; j < n; j++){
            if (!visited[j] && key[j] < min){
                index = j;
                min = key[j];
            }
        }
        visited[index] = true;
        sum += key[index];
        for (int j = 0; j < n; j++){
            if (!visited[j] && dis[index][j] < key[j]){
                key[j] = dis[index][j];
            }
        }
    }
    return sum;
}

int main()
{
    while (cin >> n && n){
        memset(dis, 0, sizeof(dis));
        memset(key, 0, sizeof(key));
        memset(visited, 0, sizeof(visited));
        for (int i = 0; i < n; i++){
            cin >> str[i];
        }
        for (int i = 0; i < n; i++){
            for (int j = i; j < n; j++){
                int tmpDis = calDis(str[i], str[j]);
                dis[i][j] = tmpDis;
                dis[j][i] = tmpDis;
            }
        }
        cout << "The highest possible quality is 1/" << prime() << '.' << endl;
    }
    return 0;
}

 

posted on 2015-10-27 20:02  caiminfeng  阅读(522)  评论(0编辑  收藏  举报

导航