poj.1789

来源:互联网 发布:怎么用网络看电视直播 编辑:程序博客网 时间:2024/05/19 02:00

这道题目的意思就是给定一系列的长度为7的串,每个串都不一样,它们中只有一个是原始串,其余串都是通过其他串改动而来,也就是说除了原始串没有父串,其余都有且仅有一个父串,定义dis为每个串与其父串不同字母的个数,则我们的目标就是寻找一个改动的方案,使得所有dis相加和最小,也即它的倒数最大,在这里我们知道a假设是b的父串,c是a的父串,显然c是b父串的父串,而如果b是c的父串,则显然不成立,因为不能循环派生吧!本题的思路就是构图,将所有的串当做点,串之间的距离dis为边,这样就可以构造一个无向连通图,而我们的任务就是求最小生成树.(想一想,为什么?,原因在前面已经说明了),但是这道题目,它的串最多为2000个,如果用kruskal算法,则要开一个2000×2000的数组,太耗内存了,而用kruskal算法则只用prim的一半内存,但同时时间效率又会远低于prim算法,最开始用kruskal算法,超时了,不过还是贴一下kruskal算法代码:

#include <stdio.h>#include <stdlib.h>#include <algorithm>#include <time.h>#define Max(a,b) (a)>(b)?(a):(b)#define Min(a,b) (a)<(b)?(a):(b)#define nodemax 2010#define edgemax 2000020struct Edge{int from;int to;int value;}edge[edgemax];char str[nodemax][8];int set[nodemax];int n;int cmp(const void *p,const void *q){return ((Edge*)p)->value>=((Edge*)q)->value;}int dis(char *p,char *q){int sum=0;for(int i=0;i<7;i++)if(p[i]!=q[i]) sum++;return sum;}int find(int x){int a=x;while(set[x]!=x)x=set[x];int j;while(x!=a){   j=set[a];   set[a]=x;   a=j;}return x;}int main(){while(scanf("%d",&n),n){int i,j;for(i=0;i<n;i++){scanf("%s",str[i]);getchar();}int k=0;for(i=0;i<n;i++)for(j=i+1;j<n;j++){    edge[k].from=i+1;edge[k].to=j+1;edge[k++].value=dis(str[i],str[j]);}clock_t s1,s2;    s1=clock();qsort(edge,k,sizeof(Edge),cmp);    for(i=1;i<=n;i++)set[i]=i;int sum=0;for(i=0;i<k;i++){int x=find(edge[i].from);int y=find(edge[i].to);if(x!=y){sum+=edge[i].value;set[Max(x,y)]=Min(x,y);}}printf("The highest possible quality is 1/%d.\n",sum);s2=clock();printf("%lf ms",double(s2-s1));}return 0;}

而用了prim算法后,ac了,这道题让我明白了两种算法的运用场合分别是什么。下面是prim算法:

#include <stdio.h>#include <stdlib.h>#include <time.h>#define Max 2010int cost[Max];int record[Max][Max];char str[Max][8];int n;int Get_min(){int MIN=Max,index;    for(int i=0;i<n;i++)if(cost[i]!=0 && cost[i]<MIN){            MIN=cost[i];    index=i;}return index;}int dis(char *p,char *q){int sum=0;for(int i=0;i<7;i++)sum+=(p[i]!=q[i]);return sum;}int kruskal(int s){int i,j;for(i=0;i<n;i++)cost[i]=record[s][i];cost[s]=0;int sum=0;for(i=0;i<n-1;i++){int index=Get_min();sum+=cost[index];cost[index]=0;for(j=0;j<n;j++)if(cost[j]!=0 && record[index][j]<cost[j])cost[j]=record[index][j];}return sum;}int main(){int i,j;while(scanf("%d",&n),n){for(i=0;i<n;i++){scanf("%s",str[i]);getchar();}for(i=0;i<n;i++)for(j=i+1;j<n;j++)record[i][j]=record[j][i]=dis(str[i],str[j]);clock_t s1,s2;s1=clock();printf("The highest possible quality is 1/%d.\n",kruskal(0));s2=clock();printf("%lf ms",double(s2-s1));}return 0;}


 


 

0 0