Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3435 | Accepted: 1254 |
Description
Input
Output
Sample Input
5 abc bcd cde aaa bfcde 0
Sample Output
8
Hint
aaa abc bcd cde bfcde
题意:给n个字符串,每两个字符串之间匹配有一个数值(匹配只能是在某一个字符串前面加空格来匹配,不是最长公共子串),然后要使整体的匹配数值最大,求最大数值。主要还是要看排列顺序是什么样。
思路:由于数据只给到10了所以直接状态压缩,因为是两两之间有个匹配值所以要预处理两两之间的匹配值然后进行状态压缩dp就好。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> #include<stack> using namespace std; typedef long long ll; char a[11][11]; int dp[1<<10][11]; int w[11][11]; void get(int x,int y) { w[x][y]=w[y][x]=0; int l1=strlen(a[x]),l2=strlen(a[y]),s=0; for(int i=0; i<l1; i++) for(int j=0; j<l2; j++) { int k=0; s=0; while(i+k<l1&&j+k<l2) { if(a[x][i+k]==a[y][j+k]) s++; k++; } if(s>w[x][y])w[x][y]=w[y][x]=s; } } int main() { int n; while(~scanf("%d",&n)&&n) { for(int i=0; i<n; i++) scanf("%s",a[i]); for(int i=0; i<n; i++) for(int j=i+1; j<n; j++) get(i,j); memset(dp,0,sizeof(dp)); for(int i=0; i<(1<<n); i++) for(int j=0; j<n; j++) if(i&(1<<j)) for(int k=0; k<n; k++) if(!(i&(1<<k))) if(dp[i][j]+w[j][k]>dp[i|(1<<k)][k]) dp[i|(1<<k)][k]=dp[i][j]+w[j][k]; int ans=0; for(int i=0; i<n; i++) ans=max(ans,dp[(1<<n)-1][i]); cout<<ans<<endl; } return 0; }