地址  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. Filter List Views 筛选器列表视图

    In this lesson, you will learn how to filter a List View. Three techniques, based on different scena ...

  2. HTML 表单模板

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. LeetCode刷题191124

    博主渣渣一枚,刷刷leetcode给自己瞅瞅,大神们由更好方法还望不吝赐教.题目及解法来自于力扣(LeetCode),传送门. 算法: 给出一个无重叠的 ,按照区间起始端点排序的区间列表. 在列表中插 ...

  4. 学习之Redis(二)

    Redis的对象和数据结构 一.字符串对象(请参考学习之Redis(一):https://www.cnblogs.com/wbq1994/p/12029516.html) 二.列表对象 列表对象的编码 ...

  5. 并发编程~~~多线程~~~线程queue, 事件event,

    一 线程queue 多线程抢占资源,只能让其串行. 互斥锁 队列 import queue q = queue.Queue() # 先进先出 q = queue.LifoQueue() # 先进后出 ...

  6. sql server编写脚本求解第1天1分钱之后每天两倍持续一个月的等比数列问题

    一.问题 问题1 场景:如果你未来的丈母娘要求你,第1天给她1分钱,第2天给2分钱,第3天给4分钱,以此类推,每天给前一天的2倍,给1个月(按30天)算就行.问:第30天给多少钱,总共给多少钱? 问题 ...

  7. qcom 8953平台 LCD亮灭屏流程及LCD知识点总结【转】

    一.LK中亮屏流程 gcdb_display_init(),进行display初始化的起始地方: oem_panel_select(),在这里去选择哪一款屏,也可以在这里添加新一款屏: dsi_pan ...

  8. 附007.Kubernetes ABAC授权

    一 ABAC 1.1 ABAC授权 基于属性的访问控制(ABAC)定义了访问控制范例,通过使用将属性组合在一起的策略向用户授予访问权限. 使用--authorization-policy-file=S ...

  9. OS X 下 OpenGL 4.x 环境配置

    配置: OS X 10.10 + CMake 3.2.2 + GLFW 3.1.1 + OpenGL 4.1 + Xcode 6.0 本文主要介绍如何在 OS X 系统下进行环境配置,使得 Xcode ...

  10. 关于ssh的几个功能

    这个有许多介绍的. 通过ssh可以实现远程shell命令行登录,x window登录,端口转发,scp文件复制,本地与远程命令间的管道连接,sftp文件传输与管理,包括同步,以及rsync文件同步,还 ...