TopCoder: SmartWordToy BFS算法

来源:互联网 发布:易语言注册登录源码 编辑:程序博客网 时间:2024/05/16 05:07

题目:SmartWordToy


思路:4个字母的单词有26 ^ 4种组合,可以看成是26 ^ 4种状态,用BFS搜索最短步骤。


代码如下:

/* *TopCoder:  SmartWordToy (http://community.topcoder.com/stat?c=problem_statement&pm=3935&rd=6532) *Author: xuzhezhao *E-mail: zhezhaoxu@gmail.com *Time: 2013/6/1 */#include <iostream>#include <queue>#include <string>#define WORDS (26 * 26 * 26 * 26)/* 单词总的组合数 */using namespace std;class SmartWordToy{public:int minPresses(string start, string finish, string forbid[]);};/* 单词状态结构 */typedef struct {string word;/* 单词 */int steps;/* 到达此状态的步骤数 */}Button;bool isForbid(string test, string forbid[]);char nextChar(char ch);char preChar(char ch);int getWordIndex(string word);bool visited[WORDS];/* 单词是否被访问的标志 */int main(){SmartWordToy toy;string start = "aaaa";string finish = "zzzz";string forbid[] = {""};/* 初始化visited数组 */for (int i = 0; i < WORDS; i++) {visited[i] = false;}cout << toy.minPresses(start, finish, forbid) << endl;return 0;}int SmartWordToy::minPresses(string start, string finish, string forbid[]){queue <Button> Q;Button button, button_temp;if (isForbid(finish, forbid)) {return -1;}button.word = start;button.steps = 0;Q.push(button);while (button.word != finish && !Q.empty()) {button = Q.front();Q.pop();/* 每次都有4个按键可以选择,每个按键可以选择向上或向下按 */for (int i = 0; i < 4; i++) {/* 向上按 */button_temp = button;button_temp.word[i] = nextChar(button_temp.word[i]);if (!visited[getWordIndex(button_temp.word)]) {visited[getWordIndex(button_temp.word)] = true;++button_temp.steps;if (!isForbid(button_temp.word, forbid)) {Q.push(button_temp);}}/* 向下按 */button_temp = button;button_temp.word[i] = preChar(button_temp.word[i]);if (!visited[getWordIndex(button_temp.word)]) {visited[getWordIndex(button_temp.word)] = true;++button_temp.steps;if (!isForbid(button_temp.word, forbid)) {Q.push(button_temp);}}}}if (button.word != finish) {return -1;} else {return button.steps;}}/** * 判断test字符串是否是满足forbid条件的字符串, * 是返回true,否则返回false. */bool isForbid(string test, string forbid[]){int i;int len;/* length of forbid  */int pos1, pos2, pos3;/* white space positons */string s0, s1, s2, s3;len = 0;while ("" != forbid[len]) {++len;}/* 当forbid数组为空时,返回false */if (0 == len) {return false;}for (i = 0; i < len; i++) {pos1 = forbid[i].find_first_of(' ', 0);pos2 = forbid[i].find_first_of(' ', pos1 + 1);pos3 = forbid[i].find_first_of(' ', pos2 + 1);s0 = forbid[i].substr(0, pos1);s1 = forbid[i].substr(pos1 + 1, pos2 - pos1 - 1);s2 = forbid[i].substr(pos2 + 1, pos3 - pos2 - 1);s3 = forbid[i].substr(pos3 + 1, forbid[i].length() - pos3 - 1);/* 如果是forbid字符串,则返回true */if (string::npos != s0.find_first_of(test[0], 0) &&string::npos != s1.find_first_of(test[1], 0) &&string::npos != s2.find_first_of(test[2], 0) &&string::npos != s3.find_first_of(test[3], 0)) {return true;}}/* 不是forbid字符串 */return false;}/** * 返回在字母表中ch的下一个字符,字母表为循环的,即z的下一个字符为a */char nextChar(char ch){if ('z' == ch) {ch = 'a';} else {++ch;}return ch;}/** * 返回在字母表中ch的上一个字符,字母表为循环的,即a的上一个字符为z */char preChar(char ch){if ('a' == ch) {ch = 'z';} else {--ch;}return ch;}/** * 返回每个单词的索引,将每个单词看成26进制数,a - z 分别表示 0 - 25, * 单词的数值就是索引值。 */int getWordIndex(string word){return ((word[0] - 'a') * (26 * 26 * 26) + (word[1] - 'a') * (26 * 26) + (word[2] - 'a') * 26 + (word[3] - 'a') );}


原创粉丝点击