您的位置:首页 > 其它

POJ1789 Truck History

2017-01-24 11:04 288 查看
用一个7位的string代表一个编号,两个编号之间的距离代表这两个编号之间不同字母的个数。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的距离,现在要找出一个“衍生”方案,使得总代价最小。
N<=2000;

´4个编号:
´aaaaaaa
´baaaaaa
´abaaaaa
´aabaaaa
    后三个均由第一个衍生可得到最小距离和1+1+1=3.

1. 所有的“衍生方案”可表示为一幅图。
    求一种“衍生方案”,实质上是去构造一棵树。
    树的顶点代表编号,树的边权代表不同编号之间的衍生代价。
    因为需要衍生出所有的方案而使总代价最小,所以要求最小生成树。

2.这是一幅稠密图,边数很多,所以选用邻接矩阵存储图、Prim算法实现最小生成树更优。

#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 999999
using namespace std;

int n,dis[2001][2001];
char s[2001][8];

int weight(int a, int b) {  //返回两个编号的衍生代价
int sum = 0;
for (int i=0; i<7; i++)
if (s[a][i] != s[b][i]) sum++;
return sum;
}

int prim() {
bool book[2001];  //book数组表示点是否被选进了树中
int ans = 0, lowd[2001], Min, k, s = 1;

memset(lowd,inf,sizeof(lowd));
memset(book,false,sizeof(book));
book[s] = true;

for (int i=1; i<n; i++) {
Min = inf;
for (int j=2; j<=n; j++) {
if (!book[j] && lowd[j] > dis[s][j])
lowd[j] = dis[s][j];
if (!book[j] && Min > lowd[j]) {
Min = lowd[j];
k = j;
}
}
book[k] = true;
s = k;  //s点不断更新
ans += Min;
}
return ans;
}

int main()
{
while (scanf("%d",&n) == 1 && n) {
for (int i=1; i<=n; i++) scanf("%s",s[i]);
for (int i=1; i<=n-1; i++)  //注意这里i和j的循环范围,避免重复赋值
for (int j=i+1; j<=n; j++)
dis[i][j] = dis[j][i] = weight(i,j);

printf("The highest possible quality is 1/%d.\n",prim());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: