您的位置:首页 > 产品设计 > UI/UE

POJ 1699 Best Sequence (TSP之dp状态压缩+KMP计算主串前缀匹配子串后缀)

2015-08-11 22:30 856 查看
题意:用最短的串,包含题目给出的所有的字符串;

据说可以用AC自动机+最短路,现在还不会,这次主要是对TSP问题进行练习,上一道TSP的题目 HDU3681 /article/8997671.html

原始的TSP问题是要走一条回路的,即汉密尔顿回路,问题变形的话,可以不回到原点,也可以有多个原点

本题 把每个串看成一个点的话,就是求不指定原点的TSP问题,且不必回到原点

把每个字符串看做是一个点,他们之间的联系是重叠的字符数量,也就是边的权重,然后建立TSP的图,再进行DP状态压缩

kmp算法,计算重叠的部分注意一点,见注释

dp[s][j]=min(dp[s-{j}][i]+dis[i][j])

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<set>
#include<stack>
#define cl(a,b) memset(a,b,sizeof(a));
#define LL long long
#define P pair<int,int>
#define X first
#define Y second
#define pb push_back
using namespace std;
const int maxn=15;
const int inf=9999999;
const int mod=100007;
int n;
char a[maxn][25];
int next[25];
void getnext(char*s){
int i=0,j=-1;
next[0]=-1;
int len=strlen(s);
while(i<len){
if(j==-1||s[i]==s[j])
next[++i]=++j;
else
j=next[j];
}
}
int kmp(char *s,char *p){

getnext(p);
int i=0,j=0;
int n=strlen(s);
int m=strlen(p);
while(i<n&&j<=m){//J<=m,否则是WA
if(j==-1||s[i]==p[j]){
i++;j++;
}
else {
j=next[j];
}
}
return m-j;
}

int dis[maxn][maxn];
void buildMap(){//建立TSP的图,一般问题变形,都需要在建立图
cl(dis,0);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j){
dis[i][j]=kmp(a[i],a[j]);
}
}
}
}
int dp[(1<<maxn)+1][maxn];
void work(){
cl(dp,-1);
for(int i=0;i<n;i++){
dp[(1<<i)][i]=strlen(a[i]);//多个起点加入到状态中
}
for(int s=0;s<(1<<n);s++){
for(int i=0;i<n;i++){
if(!(s>>i)&1)continue;//如果状态不含有i,跳过
if(dp[s][i]==-1)continue;//无法到达
for(int j=0;j<n;j++)if(i!=j){
if(s>>j&1)continue;//筛除含有j的,下面注意转移时,还要加回去
if(dp[s|(1<<j)][j]==-1)dp[s|(1<<j)][j]=dp[s][i]+dis[i][j];
dp[s|(1<<j)][j]=min(dp[s|(1<<j)][j],dp[s][i]+dis[i][j]);
}
}
}
int ans=inf;
for(int i=0;i<n;i++){
ans=min(ans,dp[(1<<n)-1][i]);
}
printf("%d\n",ans);
}

int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",a[i]);
}
//printf("%d\n",kmp(a[0],a[1]));
buildMap();
work();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: