题目连接:https://vjudge.net/contest/353606#problem/E
思路:
每次搜索最终串的当前位置的字符,因为只有四个字符,所以要找到下一个字符一定要减少这些字符串的长度,当所有子序列都满了的时候结束,重点是更新。
代码:
#include <bits/stdc++.h>
using namespace std;
const unsigned int base = 13;
char ss[12][12];
int n,T,Len[12],ans,p[12];
char op[5] = "ACTG";
struct Node
{
int len,tot;
unsigned int stu;
char p[9];
};
map <unsigned int,int> mp;
unsigned int H(char *s)
{
unsigned int tp = 0;
for(int i=0;i<n;i++)
{
tp = tp*base + s[i];
}
return tp;
}
void bfs()
{
queue <Node> q;
mp.clear();
Node t1,t2;
t1.stu = 0;
t1.len = t1.tot = 0;
for(int i=0;i<n;i++) t1.p[i] = 0;
q.push(t1);
while(!q.empty())
{
t1 = q.front();q.pop();
if(t1.len == n)
{
ans = min(ans,t1.tot);
continue;
}
for(int i=0;i<4;i++)
{
int tp = 0;
t2.len = t1.len;
t2.tot = t1.tot;
for(int j=0;j<n;j++)
{
t2.p[j] = t1.p[j];
if(t1.p[j]<Len[j] && ss[j][ t1.p[j] ] == op[i])
{
t2.p[j]++;
tp = 1;
if(t2.p[j] == Len[j]) t2.len++;
}
}
t2.stu = H(t2.p);
t2.tot++;
if(tp>0) //重点
{
if(!mp.count(t2.stu))//之前没有,要更新
{
mp[t2.stu] = t2.tot;
q.push(t2);
}
else{
if(t2.tot >= mp[t2.stu]) continue;
else{ //有了,只有更优时更新
mp[t2.stu] = t2.tot;
q.push(t2);
}
}
}
}
}
printf("%d\n",ans);
}
int main(void)
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ans = 0;
for(int i=0;i<n;i++){
scanf("%s",ss[i]);
Len[i] = strlen(ss[i]);
ans += Len[i];
}
bfs();
}
return 0;
}