【FZU - 2254】英语考试(最小生成树,思维,建图)
題干:
在過三個禮拜,YellowStar有一場專業英語考試,因此它必須著手開始復習。
這天,YellowStar準備了n個需要背的單詞,每個單詞的長度均為m。
YellowSatr準備采用聯想記憶法來背誦這n個單詞:
1、如果YellowStar憑空背下一個新詞T,需要消耗單詞長度m的精力
2、如果YellowSatr之前已經背誦了一些單詞,它可以選擇其中一個單詞Si,然后通過聯想記憶的方法去背誦新詞T,需要消耗的精力為hamming(Si, T) * w。
hamming(Si, T)指的是字符串Si與T的漢明距離,它表示兩個等長字符串之間的漢明距離是兩個字符串對應位置的不同字符的個數。
由于YellowStar還有大量繁重的行政工作,因此它想消耗最少的精力背誦下這n個單詞,請問它最少需要消耗多少精力。
Input
?
包含多組測試數據。
第一行為n, m, w。
接下來n個字符串,每個字符串長度為m,每個單詞均為小寫字母'a'-'z'組成。
?
1≤n≤1000
1≤m, w≤10
Output
輸出一個值表示答案。
Sample Input
3 4 2 abch abcd efghSample Output
10Hint
最優方案是:先憑空記下abcd和efgh消耗精力8,在通過abcd聯想記憶去背誦abch,漢明距離為1,消耗為1 * w = 2,總消耗為10。
解題報告:
? 這題巧就巧在字符串是相同長度的,所以新開一個單詞的代價都是同一個m,不然就不好處理了。最后再加上一個起始m就是答案。因為構成了一個完全圖,所以prim算法肯定更快一些。這里就不管那些了。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e6 + 5; int f[MAX]; int n,m,w; char s[1005][55]; struct Edge {int u,v;int w; } e[MAX]; bool cmp(Edge a,Edge b) {return a.w < b.w; } int getf(int v) {return v == f[v] ? v : f[v] = getf(f[v]); } void merge(int u,int v) {int t1 = getf(u);int t2 = getf(v);f[t2] = t1; } int hamming(int x,int y) {int res = 0;for(int i = 0; i<m; i++) {res += s[x][i] != s[y][i]; }return res; } int main() {while(~scanf("%d%d%d",&n,&m,&w)) {int tot = 0;for(int i = 1; i<=n*n; i++) f[i] = i;for(int i = 1; i<=n; i++) scanf("%s",s[i]);for(int i = 1; i<=n; i++) {for(int j = i+1; j<=n; j++) {e[++tot].u = i;e[tot].v = j;e[tot].w = min(w*hamming(i,j),m);}}int ans = 0;sort(e+1,e+tot+1,cmp);for(int u,v,i = 1; i<=tot; i++) {u = e[i].u,v = e[i].v;if(getf(u) != getf(v)) {merge(u,v);ans += e[i].w;}}printf("%d\n",m + ans); }return 0 ; }?
總結
以上是生活随笔為你收集整理的【FZU - 2254】英语考试(最小生成树,思维,建图)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么人死后要立刻用棉花塞住口鼻?国外也
- 下一篇: 【HDU - 5869】Differen