首页 > 代码库 > 蓝桥杯 算法提高 单词接龙 _DFS_搜索 字符串比较
蓝桥杯 算法提高 单词接龙 _DFS_搜索 字符串比较
#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <string>#include <queue>using namespace std;const int maxn = 20 + 10;int n;int ans;char ch;string dick[maxn];int use[maxn];void input();int check(int lh, int rh);void dfs(int cur, int len, bool first);void solve();void input(int n){ memset(use, 0, sizeof(use)); for (int i = 0; i < n; i++) { cin >> dick[i]; } cin >> ch;}int check(int lh, int rh){ int l_l = dick[lh].size(), r_l = dick[rh].size(); bool flag; //k: 这是"下一个字符串"的索引 for (int k = 1; k < min(l_l, r_l); k++) { flag = true; // i: 这是"前一个字符串" // i = l_l - k,代表后面的字符已经匹配, //正在尝试向前匹配寻找更长的匹配长度 // j--下一个字符串匹配索引 for (int i = l_l - k , j = 0; i < l_l && j < k; i++, j++) { if (dick[lh][i] != dick[rh][j]) { flag = false; break; } } //k为前一个字符串尾部向前和下一个字符串头部向后匹配的长度 if (flag) return k; } //没有在里面退出,说明是包含关系 or 不重复 return 0; }//last--下一个字符串索引, len -- 当前已经计算了的字符串长度 void dfs(int last, int len, bool first){ if (first) //第一次的时候 从这里开始(需要找 ch 开头的字符串) { for (int i = 0; i < n; i++) { if (dick[i][0] == ch) { if (use[i] < 2) //使用没有超过两次 { use[i]++; //从开头字符是 ch 的字符串开始递归搜索 //将first标志false dfs(i, dick[i].size(), false); use[i]--; } } } } else { //从搜索的组合中, 不断更新得到最大长度 ans = max(ans, len); for (int i = 0; i < n; i++) { //上一个字符串尾部和下一个字符串开头, //匹配的长度 int x = check(last, i); //有匹配, 且字符串使用不超过2次 if (x && use[i] < 2) { use[i]++; // 已经计算的长度 + 当前字符串长度 - 重复的长度 ==> 得到当前总长度 dfs(i, len + dick[i].size() - x, false); use[i]--; } } }}void solve(){ scanf("%d", &n); input(n); dfs(0, 1, true); cout << ans << endl; }int main(){ //测试check函数 // cin >> dick[0] >> dick[1];// cout << "debug = " << check(0, 1) << endl; solve(); return 0;}
个人总结:
通常DFS的题目,需要先写下如下模板:
const int maxn = 20 + 10;int n;int ans;char ch;string dick[maxn]; int use[maxn]; //通常这个,好多DFS题目都会用到的,用来标志使用情况,这里作用是标志使用<2次的情况void input(); //输入数据int check(int lh, int rh); //这个几乎也是都会用到的,用来检查DFS进行的条件,以及相关操作void dfs(int cur, int len, bool first); //这个当然必须写了void solve(); //程序的启动函数....
还有就是回溯的使用,通常要从搜索中寻找到最优的解,或者是寻找所有解,需要每一种情况搜索完之后,要恢复原来的值,
递归语句就放在 标志标志数组 和 去除标志数组 之间如:
ans = max(ans, len); for (int i = 0; i < n; i++) { //上一个字符串尾部和下一个字符串开头, //匹配的长度 int x = check(last, i); //有匹配, 且字符串使用不超过2次 if (x && use[i] < 2) { use[i]++; // 已经计算的长度 + 当前字符串长度 - 重复的长度 ==> 得到当前总长度 dfs(i, len + dick[i].size() - x, false); use[i]--; } }
蓝桥杯 算法提高 单词接龙 _DFS_搜索 字符串比较
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。