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;
}

  

 

posted on 2012-07-17 09:08  夜->  阅读(268)  评论(0编辑  收藏  举报