题目描述
有一个长度为 m mm 的,由 1 11 到 9 99 之间的数构成的未知数列 am a_mam。
你现在有 n nn 个线索,每个线索都是用如下方式生成的:
- 选择序列 am a_mam 的某一个位置 p pp 作为开始;
- 选择某个方向(向左或向右);
- 从 p pp 出发往你选择的方向走,每遇到一个之前未出现的数就将它加到线索中。
(可以发现,每条线索的长度都不超过 9 99。)
现在你需要求出满足所有线索的长度最小的序列的长度。
输入
第一行一个整数 n nn,表示线索的数量。
接下来 n nn 行,每行有若干个以 0 00 结尾的整数,表示一条线索。
输出
如果无解请输出 −1 -1−1,否则输出可能的最小长度。
样例输入
5
1 2 0
3 4 0
1 4 3 0
3 1 4 2 0
1 2 4 3 0
样例输出
7
提示
对于 20% 20\%20% 的数据,答案不超过 10 1010;
对于另外 40% 40\%40% 的数据,保证存在一个解,使得所有线索都可以通过从某个位置向右遍历得到;
对于 100% 100\%100% 的数据,1≤n≤10 1 \leq n \leq 101≤n≤10。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rd(){
int x=0,flg=1;
char c=getchar();
for (;(c<48||c>57)&&c!='-';c=getchar());
if (c=='-') flg=-1,c=getchar();
for (;c>47&&c<58;x=x*10+c-48,c=getchar());
return flg*x;
}
int n,m,len[11],a[11][11],b[11][11],g[11][11][11],f[11][11][11][11][1024];
bool check(int i,int j,int x){
for (int k=0;k<len[x];++k)
if (j<len[i]&&b[i][a[x][k]]==j) ++j;
else if (b[i][a[x][k]]>j) return 0;
return j==len[i];
}
int dfs(int l,int x,int r,int y,int s){
if (!x&&y==len[r]&&s==(1<<n)-1) return 0;
if (f[l][x][r][y][s]!=-1) return f[l][x][r][y][s];
int ret=0x3f3f3f3f;
if (l<n&&!x){
for (int i=0;i<n;++i)
if (!(s>>i&1))
for (int j=0;j<len[i];++j)
if (g[i][j][l]) ret=min(ret,dfs(i,j,r,y,s|1<<i));
ret=min(ret,dfs(n,0,r,y,s));
}
for (int i=0;i<n;++i)
if (!(s>>i&1)&&g[r][y][i])
ret=min(ret,dfs(l,x,i,0,s|1<<i));
for (int i=1;i<10;++i){
int fl=x&&a[l][x-1]==i,fr=y<len[r]&&a[r][y]==i;
if (fl&&fr) ret=min(ret,dfs(l,x-1,r,y+1,s)+1);
if (fl&&b[r][i]<=y) ret=min(ret,dfs(l,x-1,r,y,s)+1);
if (fr&&b[l][i]<=x) ret=min(ret,dfs(l,x,r,y+1,s)+1);
}
f[l][x][r][y][s]=ret;
return ret;
}
int main()
{
n=rd();
memset(b,0x3f,sizeof(b));
for (int i=0,j,x;i<n;len[i]=j,++i)
for (j=0,x=rd();x;++j,x=rd()) a[i][j]=x,b[i][x]=j;
for (int i=1;i<10;++i) b[n][i]=0;
for (int i=0;i<n;++i)
for (int j=0;j<len[i];++j)
for (int x=0;x<n;++x) g[i][j][x]=check(i,j,x);
for (int i=0;i<n;++i)
g[i][0][n]=1,g[n][0][i]=1;
memset(f,-1,sizeof(f));
int ans=0x3f3f3f3f;
for (int i=0;i<n;++i)
ans=min(ans,dfs(i,len[i],n,0,1<<i));
printf("%d\n",ans>100?-1:ans);
return 0;
}