Genotype:
Genotype 是一个有限的基因序列。它是由大写的英文字母A-Z组成,不同的字母表示不同种类的基因。一个基因可以分化成为一对新的基因。这种分化被一个定义的规则集合所控制。每个分化的规则可以用三个大写字母A1A2A3表示,含义为基因A1可以分化成A2A3
我们用S代表特种基因,繁殖genotype是从特种基因序列开始。根据给定的规则,它由被选择控制规则对基因不断进行繁殖而成。
任务
从文本文件GEN.IN 读入一个定义的规则集和一个想生成的genotypes 单词序列
对每一个给定的 genotype,根据给定的分化规则,检查是否它能从某一个确定特种基因序列生成,如果能,找到最小的序列长度,
将结果写入文本文件GEN.OUT.
输入
在文件GEN.IN 的第一行有一个整数n, 1 <= n <= 10000. 下面n 每一行为一个分化规则. 这些规则都由包含A – Z的三个大写字母组成.
接下来有一个整数k, 1 <= k <= 10000. 接下来的k 行有一个 genotype. Genotype由没有空格的单词组成,最多100 个英文大写字母.
输出
在文件GEN.OUT中有k行,在第I行应写入: 一个正整数――需要生成第I个genotypes的最小长度;或者单词 NIE, 如果不能生成对应的genotype。
--------------------------------------------------------------------
Ps.数据已弱化,可水过- =
读取时用一个map[A][B]数组表示 字母AB能变成的字母
由于只有26个字母,可以用一个26位的二进制数表示
进行两次动归
f[i][j]表示从字符串 从 i 到 j 能变成的字母,同理也是个二进制数
f[i][j]=f[i][j] |map[c1][c2] 存在 (f[i][k]&char[c1]&&f[k+1][j]&char[c2])
不难得到那几段字符串能变成 ‘S’
在进行一次动归
g[i]表示前 i 个字符能变成几个 ‘S’
g[i]=min(g[j]+1) 存在(f[i][j+1]&char['S'])
复杂度O(len^3*26^2)+O(len^2)
代码如下:
1 #include<cstdio> 2 #include<algorithm> 3 #include<string> 4 #include<cstring> 5 #include<iostream> 6 #include<cmath> 7 #define LL long long 8 #define INF 99999999 9 #define Min(num1,num2) if(num1>num2) num1=num2 10 #define Max(num1,num2) if(num1<num2) num1=num2 11 using namespace std; 12 int n,f[101][101],g[101],num[101],map[101][101]; 13 string s; 14 void work(){ 15 memset(f,0,sizeof f); 16 cin>>s; 17 int l=s.size(); 18 for(int k=1,i=0;i<l;k++,i++) f[k][k]=num[s[i]-'A']; 19 for(int p=1;p<=l;p++) 20 for(int i=1;i<=l;i++){ 21 int j=i+p; 22 if(j>l) break; 23 for(int k=i;k<j;k++) 24 for(int ci=0;ci<26;ci++) 25 for(int cj=0;cj<26;cj++) 26 if((f[i][k]&num[ci])&&(f[k+1][j]&num[cj])) 27 f[i][j]|=map[ci][cj]; 28 29 } 30 int key='S'-'A'; 31 for(int i=1;i<=l;i++) g[i]=INF; 32 g[0]=0; 33 for(int i=1;i<=l;i++) 34 for(int j=1;j<=i;j++) 35 if((f[j][i]&num[key])&&g[j-1]!=INF) 36 Min(g[i],g[j-1]+1); 37 g[l]==INF ? printf("NIE\n") : printf("%d\n",g[l]); 38 } 39 int main(){ 40 freopen("GEN.in","r",stdin); 41 freopen("GEN.out","w",stdout); 42 scanf("%d\n",&n); 43 num[0]=1; 44 for(int i=1;i<=26;i++) num[i]=num[i-1]<<1; 45 for(int a,b,c,i=1;i<=n;i++){ 46 a=getchar()-'A'; 47 b=getchar()-'A'; 48 c=getchar()-'A'; 49 map[b][c]|=num[a]; 50 getchar(); 51 } 52 int T; 53 scanf("%d\n",&T); 54 while(T--) work(); 55 }