地址  https://algospot.com/judge/problem/read/WORDCHAIN

解答:

1 书上的解法是制作有向图 然后查找欧拉回路  代码实现稍后

假设一定存在欧拉路径的做法

 #include <iostream>
#include <vector>
#include <string>
#include <algorithm> using namespace std; vector<vector<int>> adj; vector<string> graph[][]; vector<int> indegree, outdegree; void makeGraph(const vector<string>& words)
{
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
graph[i][j].clear();
adj = vector<vector<int>>(, vector<int>(, ));
indegree = outdegree = vector<int>(, );
for (int i = ; i < words.size(); i++) {
int a = words[i][] - 'a';
int b = words[i][words[i].size() - ] - 'a';
graph[a][b].push_back(words[i]);
adj[a][b]++;
outdegree[a]++;
indegree[b]++;
}
} void getEulerCircuit( int here,vector<int>& circuit )
{
for (int there = ; there < adj.size(); ++there) {
while (adj[here][there] > ) {
adj[here][there]--;
getEulerCircuit(there, circuit);
}
} circuit.push_back(here);
} vector<int> getEulerTrailOrCircuit()
{
vector<int> circuit; for (int i = ; i < ; i++) {
if (outdegree[i] == indegree[i] + ) {
getEulerCircuit(i, circuit);
return circuit;
}
} for (int i = ; i < ; ++i)
{
if (outdegree[i]) {
getEulerCircuit(i, circuit);
return circuit;
}
} return circuit;
} string solve(const vector<string>& words)
{
makeGraph(words); vector<int> circuit = getEulerTrailOrCircuit(); if (circuit.size() != words.size() + ) return "IMPOSSIBLE"; reverse(circuit.begin(), circuit.end());
string ret;
for (int i = ; i < circuit.size(); i++) {
int a = circuit[i - ], b = circuit[i];
if (ret.size()) ret += " ";
ret += graph[a][b].back();
graph[a][b].pop_back();
} return ret;
} int n, m;
int main()
{
cin >> n;
while (n--) {
cin >> m;
vector<string> words;
while (m--) {
string s;
cin >> s;
words.push_back(s);
} cout << solve(words) << endl; } return ;
}

先统计有向图的出入度 判断有无欧拉回路与欧拉路径后 在进行dfs的做法

 #include <iostream>
#include <vector>
#include <string>
#include <algorithm> using namespace std; vector<vector<int>> adj; vector<string> graph[][]; vector<int> indegree, outdegree; void makeGraph(const vector<string>& words)
{
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
graph[i][j].clear();
adj = vector<vector<int>>(, vector<int>(, ));
indegree = outdegree = vector<int>(, );
for (int i = ; i < words.size(); i++) {
int a = words[i][] - 'a';
int b = words[i][words[i].size() - ] - 'a';
graph[a][b].push_back(words[i]);
adj[a][b]++;
outdegree[a]++;
indegree[b]++;
}
} void getEulerCircuit(int here, vector<int>& circuit)
{
for (int there = ; there < adj.size(); ++there) {
while (adj[here][there] > ) {
adj[here][there]--;
getEulerCircuit(there, circuit);
}
} circuit.push_back(here);
} string solve(const vector<string>& words)
{
makeGraph(words); int start = -; int end = -; for (int i = ; i < ; i++) {
if (outdegree[i] != indegree[i]) {
if (outdegree[i] == indegree[i] + ) {
if (- == start)
start = i;
else
return "IMPOSSIBLE";
}
else if (outdegree[i] + == indegree[i] ) {
if( - == end)
end = i;
else
return "IMPOSSIBLE";
}
}
} vector<int> circuit;
if (start == - && end == -) {
for (int i = ; i < ; ++i)
{
if (outdegree[i]) {
getEulerCircuit(i, circuit);
break;
}
}
}
else {
getEulerCircuit(start, circuit);
} reverse(circuit.begin(), circuit.end());
string ret;
for (int i = ; i < circuit.size(); i++) {
int a = circuit[i - ], b = circuit[i];
if (ret.size()) ret += " ";
ret += graph[a][b].back();
graph[a][b].pop_back();
} return ret;
} int n, m;
int main()
{
cin >> n;
while (n--) {
cin >> m;
vector<string> words;
while (m--) {
string s;
cin >> s;
words.push_back(s);
} cout << solve(words) << endl; } return ;
}

2 个人觉得 可以使用首尾单词作为关键字 去哈希 然后进行哈希查找与DFS结合的搜索 看看最后能否将单词全部使用 代码如下

TLE

 #include <iostream>
#include <vector>
#include <string> using namespace std; int n, m; /*
3
4
dog
god
dragon
need
3
aa
ab
bb
2
ab
cd need dog god dragon
aa ab bb
IMPOSSIBLE
*/ vector<string> ret; void Dfs( int begIdx,vector<vector<vector<string>>>& vvstr)
{
if (ret.size() == m) {
return;
} for (int i = ; i < ; i++) {
for (int j = ; j < vvstr[begIdx][i].size(); j++) {
//选择 nextBegIdx 开头的字母
//如果已经选择过了 则进行下一次尝试
if (vvstr[begIdx][i][j][] == '#')
continue; //开始选择该单词接龙
int nextBegIdx = vvstr[begIdx][i][j].back() - 'a';
ret.push_back(vvstr[begIdx][i][j]);
vvstr[begIdx][i][j][] = '#'; //修改字符串的第一个字符 作为已经被选择的标记 Dfs( nextBegIdx, vvstr); if (ret.size() == m) {
return;
} vvstr[begIdx][i][j][] = 'a'+ begIdx;
ret.pop_back();
break;
}
} } void DfsStart(vector<vector<vector<string>>>& vvstr)
{
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
for (int k = ; k < vvstr[i][j].size(); k++) {
//选中这个单词作为开始
int nextBegIdx = vvstr[i][j][k].back() - 'a';
ret.push_back(vvstr[i][j][k]);
vvstr[i][j][k][] = '#'; //修改字符串的第一个字符 作为已经被选择的标记
Dfs( nextBegIdx,vvstr); if (ret.size() == m) {
return;
} //复原 继续下一次选择
vvstr[i][j][k][] = 'a'+i;
ret.pop_back();
break;
}
}
} } int main()
{
cin >> n;
while (n--) {
cin >> m;
string s; vector<vector<vector<string>>> vvstr(, vector<vector<string>>(, vector<string>()));
ret.clear();
for (int i = ; i < m; i++){
cin >> s;
int beg = s[] - 'a';
int end = s.back() - 'a';
vvstr[beg][end].push_back(s);
}
DfsStart(vvstr);
if(!ret.empty()){
for (int i = ; i < ret.size(); i++) {
cout << ret[i] << " ";
}
}
else {
cout << "IMPOSSIBLE";
}
cout << endl;
} return ;
}

算法问题实战策略 WORDCHAIN的更多相关文章

  1. 算法问题实战策略 PICNIC

    下面是另一道搜索题目的解答过程题目是<算法问题实战策略>中的一题oj地址是韩国网站 连接比较慢 https://algospot.com/judge/problem/read/PICNIC ...

  2. 《算法问题实战策略》-chaper7-穷举法

    关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者 ...

  3. 《算法问题实战策略》-chaper32-网络流

    基本的网络流模型: 在图论这一块初步的应用领域中,两个最常见的关注点,其一时图中的路径长度,也就是我们常说的的最短路径问题,另一个则是所谓的“流问题”. 流问题的基本概念: 首先给出一张图. 其实所谓 ...

  4. 《算法问题实战策略》-chaper13-数值分析

    这一章节主要介绍我们在进行数值分析常用的二分.三分和一个近似求解区间积分的辛普森法. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解 ...

  5. 《算法问题实战策略》——chaper9——动态规划法技巧

    Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1)    拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2)    棋盘中还剩 ...

  6. 《算法问题实战策略》-chaper8-动态规划法

    Q1:偶尔在电视上看到一些被称为“神童”的孩子们背诵小数点以后几万位的圆周率.背诵这么长的数字,可利用分割数字的方法.我们用这种方法将数字按照位数不等的大小分割后再背诵. 分割形式如下: 所有数字都相 ...

  7. 《算法问题实战策略》-chaper21-树的实现和遍历

    这一章节开始介绍一个数据结构中的一个基本概念——树. 我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列.数组和链表等结构表征),还有一个重要的特性——层级结构 ...

  8. 算法问题实战策略 QUADTREE

    地址 https://algospot.com/judge/problem/read/QUADTREE 将压缩字符串还原后翻转再次压缩的朴素做法 在数据量庞大的情况下是不可取的 所以需要在压缩的情况下 ...

  9. 算法问题实战策略 DICTIONARY

    地址 https://algospot.com/judge/problem/read/DICTIONARY 解法 构造一个26字母的有向图 判断无回路后 就可以输出判断出来的字符序了 比较各个字母的先 ...

随机推荐

  1. echarts 部分美化配置项使用记录

    一.图表背景色配置项,如背景颜色渐变 https://www.echartsjs.com/zh/option.html#backgroundColor 二.图表中图形的颜色,如柱状图行采用渐变颜色显示 ...

  2. Python Exception处理

    Python中的错误处理分为两类:语法错误和异常处理.语法错误一般是指由于python语句.表达式.函数等存在书写格式活语法规则上的错误抛出的异常,如python常见的缩进控制,若同层次的执行语句存在 ...

  3. 44-创建 Machine

    对于 Docker Machine 来说,术语 Machine 就是运行 docker daemon 的主机.“创建 Machine” 指的就是在 host 上安装和部署 docker.先执行 doc ...

  4. mysql初始化/usr/local/mysql/bin/mysqld: error while loading shared libraries: libnuma.so.1: cannot open shared object file: No such file or directory

    [root@test153 ~]# /usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql - ...

  5. java 监听文件或文件夹变化

    今天遇到一个新需求,当从服务器下载文件后用指定的本地程序打开,不知道何时文件下载完成,只能考虑监听文件夹,当有新文件创建的时候打开指定程序. 在此给出一个完整的下载和打开过程: 1.下载文件 jsp页 ...

  6. Redis内存数据库在Exchange会议室的整体应用架构

    注:本文是别人写的,感觉写得很好就转过来,版权归原作者所有哦,谁知道出处可以告诉我,谢谢. 根据以上的会议室应用现状分析,该架构的核心是把历史发生的会议室申请数据定时同步到Redis内存数据库中,对于 ...

  7. 使用Active Database Duplication创建跨平台Data Guard设置 (Windows/Linux) (Doc ID 881421.1)

    Using Active Database Duplication to Create Cross Platform Data Guard Setup (Windows/Linux) (Doc ID ...

  8. 如何在Mac上使用Siri

    在您的iPhone上,要求Siri执行命令很简单.但是,如果在计算机上工作时附近没有iPhone,会发生什么情况?您也可以在Mac上使用Siri.快速简便,使其成为iMac或MacBook的完美伴侣. ...

  9. Java之Collection接口(单列集合根接口)

    集合概述 集合到底是什么呢?集合:集合是java中提供的一种容器,可以用来存储多个数据 集合和数组既然都是容器,它们有啥区别呢? 区别1: 数组的长度是固定的. 集合的长度是可变的. 区别2:  数组 ...

  10. 【使用篇二】Quartz自动化配置集成(17)

    出处:https://www.jianshu.com/p/49133c107143 定时任务在企业项目比较常用到,几乎所有的项目都会牵扯该功能模块,定时任务一般会处理指定时间点执行某一些业务逻辑.间隔 ...