sgu 327

想了半天。。发现居然是一个最短哈密顿路的模型(注意不是环。。)
首先把被包含的扔掉。。那么建立N个顶点代表字符串。。
两点的距离就是这两个字符串接起来增加的字符数*2。。
图是完全的。。边是有向的。。
那么用集合DP就可以搞定了。。先要枚举开始的顶点。。
复杂度就是(N^3*2^N)。。也能过。。
。。正在写。。
写了半天。。弄了个半成品。。路径实在不想写了。。只能算个答案
注意一下。。连接的话有4种方式(T表示正的放。。R表示反着放)
T<- T R -> R
R<- R T -> T
T<- R T -> R
R<- T R -> T
。。。BT。。。
这么搞的话再构造方案岂不是要死人阿。。
Code。。
#include<string>
#include<iostream>
#include<queue>
#define REP(i,n) for(int i=0;i<n;i++)
using namespace std;
const int maxn=14,inf=~0U>>1;
int N=0,ans=~0U>>1;
string B[maxn];
int dist[maxn][maxn];
string Reverse(string tmp)
{
for(int s=0,t=tmp.length()-1;s<t;s++,t–) swap(tmp[s],tmp[t]);
return tmp;
}
int maxcommon(const string&x,const string&y)
{
int ans=0;
for(int i=1;i<=min(x.length(),y.length());i++)
if(x.substr(x.length()-i,i)==y.substr(0,i))
ans=i;
return ans;
}
void init()
{
int cnt;cin>>cnt;
string A[maxn];
for(int i=0;i<cnt;i++)
cin>>A[i];
for(int i=0;i<cnt;i++)
{
bool find=false;
for(int j=0;j<cnt;j++) if(j!=i)
if(A[j].find(A[i])!=string::npos)
{find=true;break;}
if(!find)
B[N++]=A[i];
}
for(int i=0;i<N;i++)
for(int j=0;j<N;j++) if(i!=j)
{
int a=B[j].length()*2-maxcommon(B[j],B[i])*2;
int b=B[j].length()*2-maxcommon(Reverse(B[j]),B[i])*2;
int c=B[j].length()*2-maxcommon(B[j],Reverse(B[i]))*2;
int d=B[j].length()*2-maxcommon(Reverse(B[j]),Reverse(B[i])))*2;
dist[i][j]=min(min(min(a,b),c),d);
}
}
int DP[1<<maxn][maxn];
struct node
{
int state,pos;
node(int s,int p):state(s),pos(p){}
};
void start(int i)
{
string tmp=Reverse(B[i]);
REP(j,1<<N) REP(k,N) DP[j][k]=inf;
DP[1<<i][i]=B[i].length()*2-maxcommon(B[i],tmp);
queue<node> Q;
Q.push(node(1<<i,i));
while(Q.size())
{
node cur=Q.front();Q.pop();
int s=cur.state,p=cur.pos;
for(int j=0;j<N;j++) if(s^(1<<j))
{
int ns=s^(1<<j),get=DP[s][p]+dist[p][j];
if(DP[ns][j]>get)
DP[ns][j]=get,Q.push(node(ns,j));
}
}
REP(j,N) if(DP[(1<<N)-1][j]<ans)
ans=DP[(1<<N)-1][j];
}
void solve()
{
for(int i=0;i<N;i++)
start(i);
cout<<ans<<endl;
}
int main()
{
init();
solve();
}

Leave a Reply

Your email address will not be published. Required fields are marked *