CODEVS-1018单词接龙
单词接龙
原题:传送门
解题思路:
- 此题是典型的深搜题目,首先确定递归变量,表示字母的数量,每当满足一定条件,就往下一层递归,否则回溯
- 判断由哪个单词开始(因为可能字母首位可能相同),再确定之后所连单词,还需要标记数组防止重复选择
- 小心题目要求,每个单词最多可以出现两次,开始的时候字母弄成两个即可,还有字母之间不能包含,循环时注意下长度
核心代码:
1 /* 2 string类稍微方便一些,记得最后比较长度 3 */ 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 using namespace std; 8 9 string str[44]; 10 int mark[44], label[44], len[44], sum, n, ans; 11 char c; 12 13 //mark标记是否用过该字母,label记住该字母在str数组中下标,len记住该字母长度 14 void dfs(int k) 15 { 16 if (k == 1){//确定首位 17 for (int i = 1; i <= 2 * n; i += 2){ 18 if (mark[i] == 0 && str[i][0] == c){ 19 sum += str[i].length(); mark[i] = 1; label[k] = i; len[k] = str[i].length(); 20 dfs(k + 1); 21 sum -= len[k]; mark[i] = 0;//回到上一步,清除标志 22 } 23 } 24 } 25 else{ 26 for (int i = 1; i <= 2 * n; i++){//这里是i++表示每个字母都会遍历两遍 27 if (mark[i] == 0){ 28 bool judge = false; 29 int pre = label[k - 1], j; 30 int len1 = str[pre].length(), len2 = str[i].length(); 31 int Len = min(len1, len2);//字符串不能包含,题意 32 for (j = 1; j < Len; j++) 33 { //substr函数返回子字符串,(开始位置,长度) 34 if (str[pre].substr(len1 - j, j) == str[i].substr(0, j)) 35 { 36 judge = true; 37 break; 38 } 39 } 40 if (judge) 41 { 42 mark[i] = 1; label[k] = i; len[k] = len2 - j; sum += len[k]; 43 dfs(k + 1); 44 mark[i] = 0; sum -= len[k];//回到上一步,清除标记 45 } 46 } 47 } 48 } 49 ans = max(ans, sum);//最后比较最长是多少 50 } 51 int main() 52 { 53 cin >> n; 54 for (int i = 1; i <= 2 * n; i += 2){ 55 cin >> str[i]; 56 str[i + 1] = str[i];//每个字母最多使用两次 57 } 58 cin >> c; 59 dfs(1); 60 cout << ans << endl; 61 return 0; 62 }