#include #include #include #include #include using namespace std; //"Infinity" value indicating no solution exists #define INF 10000 vector >rules; int memo[50][50][20]; string worm; /* Recursive function (with memorization) to find the minimum number of days it could take to form the substring from index "start" to "end" of the worm, starting with the target letter.*/ int recurse(int start, int end, int targetLetter) { //If the substring has 1 letter, it's either targetLetter or it isn't! if (start == end) { if (worm[start] - 'A' == targetLetter) return 0; return INF; } //If we've already processed this input, return the memoized result if (memo[start][end][targetLetter] > 0) return memo[start][end][targetLetter]; int theMin = INF; /* Strategy: We know that the target letter was first transformed into 2 different letters. Then the 1st letter formed into the 1st part of the string, whle the 2nd letter formed into the 2nd part. Choose the set of 2 letters, and the way to divide up the string, to minimize the number of days this takes.*/ //Try each possible way to divide the string into 2 parts for (int mid = start; mid < end; mid++) { //Try each possible rule that could be used to form targetLetter for (int rule = 0; rule < rules[targetLetter].size(); rule++) { int firstLetter = rules[targetLetter][rule][0] - 'A'; int secondLetter = rules[targetLetter][rule][1] - 'A'; int result = 1 + max( recurse(start, mid, firstLetter), recurse(mid+1, end, secondLetter)); theMin = min(theMin, result); } } memo[start][end][targetLetter] = theMin; return theMin; } int main() { ifstream infile("worms.in"); ofstream outfile("worms.out"); while(true) { //clear lists of rules and memoization list rules = vector >(20); for (int i = 0; i < 50; i++) for (int j = 0; j < 50; j++) for (int k = 0; k < 20; k++) memo[i][j][k] = 0; int numRules; infile >> numRules; if (numRules == 0) return 0; //Input all the rules for (int i = 0; i < numRules; i++) { string str; infile >> str; int index = str[0] - 'A'; rules[index].push_back(str.substr(1)); } infile >> worm; //Find the min. number of days needed to form the worm from each letter. int theMin = INF; for (int i = 0; i < 20; i++) { theMin = min(theMin, recurse(0, worm.length()-1, i)); } if (theMin == INF) outfile << -1 << endl; else outfile << theMin << endl; } system("PAUSE"); return 0; }