题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3722
1 /* 2 问题 3 将任意的两个字符串进行匹配,使得匹配后权值和最大 4 5 解题思路 6 将任意的字符串的权值计算出来,使用KM算法即可。 7 */ 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 using namespace std; 12 13 const int maxn=210; 14 int W[maxn][maxn],n; 15 char s[maxn][1100]; 16 int lx[maxn],ly[maxn]; 17 int left[maxn]; 18 bool S[maxn],T[maxn]; 19 int len[maxn]; 20 21 void presolve(); 22 int KM(); 23 bool match(int i); 24 void update(); 25 26 int main() 27 { 28 int i,j; 29 while(scanf("%d",&n) != EOF) 30 { 31 for(i=1;i<=n;i++) 32 { 33 scanf("%s",s[i]); 34 len[i]=strlen(s[i]); 35 } 36 presolve(); 37 38 printf("%d\n",KM()); 39 } 40 } 41 42 bool match(int i) 43 { 44 S[i]=true; 45 for(int j=1;j<=n;j++) if(lx[i]+ly[j] == W[i][j] && !T[j]){ 46 T[j]=true; 47 if(!left[j] || match(left[j])){ 48 left[j]=i; 49 return true; 50 } 51 } 52 return false; 53 } 54 55 void update() 56 { 57 int a= 1<<30; 58 for(int i=1; i<=n; i++){ 59 if(S[i]){ 60 for(int j=1;j<=n;j++){ 61 if(!T[j]){ 62 a = min(a,lx[i]+ly[j] - W[i][j]); 63 } 64 } 65 } 66 } 67 68 for(int i=1;i<=n;i++){ 69 if(S[i]) lx[i] -= a; 70 if(T[i]) ly[i] += a; 71 } 72 } 73 74 int KM() 75 { 76 for(int i=1;i<=n;i++){ 77 left[i] = lx[i] = ly[i] = 0; 78 for(int j=1; j<=n; j++) 79 lx[i]=max(lx[i],W[i][j]); 80 } 81 82 for(int i=1; i<=n; i++){ 83 for(;;){ 84 for(int j=1;j<=n;j++){ 85 S[j]=T[j]=0; 86 } 87 if(match(i)) break; 88 else update(); 89 } 90 } 91 92 int ans=0; 93 for(int i=1;i<=n;i++) 94 ans += W[left[i]][i]; 95 return ans; 96 } 97 98 void presolve() 99 { 100 int i,j,k,p1,p2,cnt; 101 for(i=1;i<=n;i++) 102 { 103 for(j=1;j<=n;j++) 104 { 105 if(i==j) 106 { 107 W[i][j]=0; 108 continue ; 109 } 110 111 cnt=0; 112 p1=len[i]-1; 113 p2=0; 114 while(1) 115 { 116 if(s[i][p1]==s[j][p2]) cnt++; 117 else break ; 118 p1--,p2++; 119 if(p1<0 || p2>=len[j]) break ; 120 } 121 W[i][j]=cnt; 122 } 123 } 124 }
原文地址:https://www.cnblogs.com/wenzhixin/p/9053758.html
时间: 2024-10-12 03:04:57