http://poj.org/problem?id=1699
题目大意:
给你n个字符串 可以让他们任意首尾合并相连
求包含所以字符串的最短总字符串长度
注意:
只能首尾合并相连 像 ACTG 和 CT 是不可以的
思路:
求出所以成对字符串合并会增加多少长度 并记录在表中
然后Dfs搜索就可以啦 剪枝效果更好
代码及其注释:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
const int N=11;
char s[N][N*2];
int l[N];
int addl[N][N];
bool had[N];
int ans, n;
void Findaddl(int I,int J)
{
int w,i,j;
for(w=max(0,l[I]-l[J]);w<l[I];++w)
{
for(i=w,j=0;j<l[J]&&i<l[I];++j,++i)
{
if(s[I][i]!=s[J][j])
break;
}
if(j==l[J]||i==l[I])
break;
}
if(j==l[J])
addl[I][J]=0;
else
addl[I][J]=w+l[J]-l[I];
}
void Dfs(int sum,int Len,int pre)
{
for(int i=0;i<n;++i)
{
if(!had[i])
{
had[i]=true;
if(sum==n)
{
ans=min(ans,Len+addl[pre][i]);//枚举最小 答案
}
else if(Len+addl[pre][i]<ans)//剪枝
{
Dfs(sum+1,Len+addl[pre][i],i);
}
had[i]=false;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
getchar();
ans=0;
for(int i=0;i<n;++i)
{
gets(s[i]);
l[i]=strlen(s[i]);//求长度
ans+=l[i];//记录长度和 这个和是最大长度可能
}
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
if(i!=j)
Findaddl(i,j);//求i 和 j 首尾合并增加多少长度
}
}
memset(had,false,sizeof(had));
for(int i=0;i<n;++i)
{
had[i]=true;
Dfs(2,l[i],i);//深搜
had[i]=false;
}
printf("%d\n",ans);
}
return 0;
}