http://codeforces.com/contest/653/problem/B
给你n,q
q是置换规则,每一个规则把2个字母置换成1个
要求你构造出一个长度为n的字符串,使得满足:
每次取最前两个字母进行置换,最终整个字符串能变成 一个字母a
数据太小。暴力dp一下就好。。。
初始化,dp[1][i]=1
之前先把两个字母和一个字母映射起来,
dp[i][j]表示第i次置换是字符串J (两个字母叫字符串)
对dp[i][j]!=0时;
在map表里找到 字符串j 置换成的 字母。
然后如果该字母+(a到f)能构成一个新的可置换字符串,则dp[i][new]+=dp[i][j],new是新字符串的序号
最后把dp[n-1][j]中,字符串【j】置换结果==‘a’的答案都加起来就OK
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
int min(int a,int b)
{return a<b?a:b;}
int max(int a,int b)
{return a>b?a:b;}
string aa[38];
char bb[38];
int dp[30][38];
map<string,char>sb,num;
int main()
{
int i,j;
int n,q;
cin>>n>>q;
for (i=1;i<=q;i++)
{
cin>>aa[i]; cin>>bb[i];
sb[aa[i]]=bb[i];
num[aa[i]]=i;
}
for (i=1;i<=q;i++)
dp[1][i]=1;
for (i=1;i<=n-2;i++)
{
for (j=1;j<=q;j++)
{
if (dp[i][j]==0) continue;
for (char tt='a';tt<='f';tt++)
{
string tmp;tmp=sb[aa[j]];
tmp+=tt;
if (sb.count(tmp)==0) continue;
dp[i+1][num[tmp]]+=dp[i][j];
}
}
}
int sum=0;
for (i=1;i<=q;i++)
if (dp[n-1][i])
{
if (sb[aa[i]]=='a')
sum+=dp[n-1][i];//printf("%d:%d\n",i,dp[n-1][i]);
}
printf("%d\n",sum);
return 0;
}