洛谷p1019 单词接龙

题意:输入一系列单词,输入一个字母,求出以这个字母开头,由输入单词拼接成的一个最长字符串的长度,每个单词可以出现两次,两个拼接在一起的单词带有重叠部分但是彼此不能有包含关系

这是一道dfs的题目,之前想到dfs, bfs总是自觉的想到一个二维数组找路径之类的问题,刚看这题时完全想不到如何用dfs求解,这道题让我更加了解了dfs搜索的本质,其实和暴力枚举类似,就是地毯式搜索,搜索每一种情况

思路是先对输入数据做一次处理,算出它们每一个单词与其它单词重叠部分的最小长度(因为最后要求拼接成最长的一个单词)

然后遍历每个单词,若首字母为给定字母则开始搜索(若理解不了这里搜索的意思,可以将其看成枚举,多做几道入门经典dfs题目可对其有更深理解)

#include<bits/stdc++.h>
using namespace std;

int ans;
int n;
int vis[20];
int cl[20][20];
char c;
string words[20];

int commenlength(string a, string b){
  int minlen = 50;
  for(int i=0; i<a.length(); i++){
      int m = a.length()-1;
      int n = i;
      bool flag = true;

      while(m>=0 && n>=0){
        if(a[m] == b[n]){
          m--;
          n--;
        }else{
          flag = false;
          break;
        }
      }

      if(flag)
        minlen = min(i+1, minlen);
  }
  return minlen == 50?0 : minlen;
}

void dfs(int length, int idx){
  ans = max(length, ans);
  for(int i=0; i<n; i++){
    if(vis[i] < 2){
      if(cl[idx][i] >= 1 && cl[idx][i] != words[idx].length() && cl[idx][i] != words[i].length()){
        vis[i]++;
        dfs(length + words[i].length()-cl[idx][i], i);
        vis[i]--;
      }
    }
  }

}

int main(){
  ios::sync_with_stdio(false);

  cin >> n;
  for(int i=0; i<n; i++)
    cin >> words[i];

  for(int i=0; i<n; i++){
    for(int j=0; j<n; j++){
      cl[i][j] = commenlength(words[i], words[j]);
    }
  }

  cin >> c;
  for(int i=0; i<n; i++){
    if(words[i][0] == c){
      vis[i]++;
      dfs(words[i].length(), i);
      vis[i]--;
    }
  }

  cout << ans;
  return 0;
}
原文地址:https://www.cnblogs.com/ssNiper/p/11253326.html