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])
据说可以用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; }
相关文章推荐
- UINavigationBar & UINavigationItem
- 视图UIView的frame、bounds与center属性
- LeetCode(187) Repeated DNA Sequences
- request.getParameterValues与request.getParameter的区别
- request.getParameterValues与request.getParameter的区别
- UIAutomation调用计算器模拟自动执行
- iOS UILocalNotification定时提醒
- 更新UI方式
- Divide and Conquer.(Merge Sort) by sixleaves
- Handler与looper、MessageQueue的关系
- *** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit_Sim/UIKit
- hdu5064 Find Sequence 单调性dp
- 自定义iOS UIpagecontrol 小圆点 换上自定义图片
- iOS基础-UIKit框架-高级视图-UIPickerView-实例3:国家选择(图片)
- UITableView(基本设置和常用的协议方法)
- UITableView的编辑
- 窗口与视图UIScreen and UIView
- Blue Jeans(POJ--3080
- 2015 Multi-University Training Contest 6 (hdu 5357 - Easy Sequence)栈的应用
- 深入理解urllib、urllib2及requests