题目链接:点击打开链接
题目大意:
给你不超过10个长度不超过20的字符串,如果某两个字符串的首尾相同或没有相同,都可以连接起来,例如TCGG和GGAT就可以连接为TCGGAT,问把给你的所有字符串都按
照这种规则连接起来,最短长度是多少?
题目解析:
首先因为n和字符串长度都很小,我们可以直接模拟处理出每个字符串两两之间的可以合并的长度是多少,例如TCGG和GGAT的可合并的长度为2,那么给每个字符串编号之
后,我们可以得到一个n*n的矩阵,然后直接深搜就可以了,注意处理细节题目所求的总的长度,例如a在前b在后,所以对于a字符串就是字符串的长度len,之后都是
len+b.len-cal(a,b);
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int m = 100007;
const double esp = 1e-6;
const double PI = 3.14159265359;
const int INF = 0x3f3f3f3f;
using namespace std;
const int maxn = 105;
char arr[15][maxn];
int Map[15][15],ans;
int arr_size[15];
bool vis[maxn];
int cal(char a[],char b[]){
int lena = strlen(a);
int lenb = strlen(b);
int num = 0,Min = min(lena,lenb);
for(int i=Min;i>=1;i--){
int l = lena - i,r = 0,f = 1;
for(int j=lena - i;j<lena;j++){
if(a[j] != b[r]){
f = 0;
}
r += 1;
}
if(f)
return i;
}
return 0;
}
void faw(int x,int s,int num,int n){
if(s == n){
ans = min(ans,num);
return ;
}
for(int i=0;i<n;i++){
if(!vis[i]){
vis[i] = 1;
faw(i,s + 1,num + arr_size[i] - Map[x][i],n);
vis[i] = 0;
}
}
}
int main(){
int t,n;
scanf("%d",&t);
while(t-- && ~scanf("%d",&n)){
for(int i=0;i<n;i++){
scanf("%s",arr[i]);
arr_size[i] = strlen(arr[i]);
}
memset(Map,0,sizeof(Map));
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
Map[i][j] = cal(arr[i],arr[j]);
Map[j][i] = cal(arr[j],arr[i]);
}
}
memset(vis,false,sizeof(vis));
ans = INF;
for(int i=0;i<n;i++){
vis[i] = true;
faw(i,1,arr_size[i],n);
vis[i] = false;
}
printf("%d\n",ans);
}
return 0;
}