標籤:blog http os io for 問題
題意:用一個7位的字串代表一個編號,這兩個編號之間不同字母的個數等於兩個編號之間的距離。一個編號只能由另一個編號“衍生”出來,代價是這兩個編號之間相應的distance,現在要找出一個“衍生”方案,使得總代價最小,也就是distance之和最小。
案例說明:
1.aaaaaaa
2.baaaaaa
3.abaaaaa
4.aabaaaa
1和2,3,4之間的距離都為1,2和3的距離為2,2和4的距離為2,3和4的距離為2.
顯然的,第二,第三和第四編號分別從第一編號衍生出來的代價最小,因為第二,第三和第四編號分別與第一編號只有一個字母是不同的,相應的distance都是1,加起來是3。也就是最小代價為3。
問題可以轉化為最小代價產生樹的問題。
此題的關鍵是將問題轉化為最小產生樹的問題。每一個編號為圖的一個頂點,頂點與頂點間的編號差即為這條邊的權值,題目所要的就是我們求出最小產生樹來。這裡我用prim演算法來求最小產生樹。
構造最小產生樹鄰接矩陣:
for(i=0;i<t;i++) { for(j=i+1;j<t;j++) { num=cal(s[i].str,s[j].str); G[i][j]=G[j][i]=num; } }
cal函數為計算兩字串之間的距離:
int cal(char s1[],char s2[]){ int i,num=0; for(i=0;i<7;i++) if(s1[i]!=s2[i]) num++; return num;}
完成這步直接調用prim函數即可。
附上AC代碼:
#include <stdio.h>#include <string.h>#include <stdlib.h>#define infinity 1000000#include<iostream>#include<algorithm>using namespace std;struct node{ char str[8];}s[2001];int N;int G[2000][2000];int lowcost[100000];int used[100000];int cal(char s1[],char s2[]){ int i,num=0; for(i=0;i<7;i++) if(s1[i]!=s2[i]) num++; return num;}int prim(int vcount){ int sum=0; int i,j,k; int min; for (i=0; i<vcount; i++) { lowcost[i]=G[0][i]; used[i]=0; } used[0]=1; for (i=1; i<=vcount-1; i++) { j=0; min = infinity; for (k=1; k<vcount; k++) if ((!used[k])&&(lowcost[k]<min)) { min = lowcost[k]; j=k; } used[j]=1; sum+=min; for (k=1; k<vcount; k++) if (!used[k]&&(G[j][k]<lowcost[k])) { lowcost[k]=G[j][k]; } } return sum;}int main(){ int t,i,j,num,sum; while(scanf("%d",&t)!=EOF&&t) { getchar(); for(i=0;i<t;i++) { gets(s[i].str); } for(i=0;i<t;i++) { for(j=i+1;j<t;j++) { num=cal(s[i].str,s[j].str); G[i][j]=G[j][i]=num; } } sum=prim(t); printf("The highest possible quality is 1/%d.\n",sum); } return 0;}
prim演算法詳見:http://www.cnblogs.com/PJQOOO/p/3855017.html
————Anonymous.PJQ